[Rcpp-devel] coercion NULL to vector

Dirk Eddelbuettel edd at debian.org
Tue Apr 17 17:53:48 CEST 2018


On 17 April 2018 at 10:31, Dirk Eddelbuettel wrote:
| 
| On 17 April 2018 at 15:09, Serguei Sokol wrote:
| | Hi,
| | 
| | I would like to re-discuss the subject of automatic coercion of
| | NULL to some vector in function parameter list. This old topic was
| | already raised e.g. here
| | https://stackoverflow.com/questions/34718570/rcpp-pass-vector-of-length-0-null-to-cppfunction
| | 
| | To resume, actually a function defined as (ivec is from RcppArmadillo package)
| | 
| | sourceCpp(code="
| |      // [[Rcpp::depends(RcppArmadillo)]]
| |      #include <RcppArmadillo.h>
| |      using namespace arma;
| |      // [[Rcpp::export]]
| |      ivec f(ivec x) {return x+1;}
| | ")
| | 
| | and called as f(c()) will produce an error:
| | Error in f(c()) :
| |    Not compatible with requested type: [type=NULL; target=integer].
| | 
| | What I propose is (for this example) to mimic a call f(integer(0)) which gives:
| |  > f(integer(0))
| |       [,1]
| | 
| | The following one-line patch would do the job:
| | diff --git a/inst/include/Rcpp/r_cast.h b/inst/include/Rcpp/r_cast.h
| | index e59fa799..c0ec0817 100644
| | --- a/inst/include/Rcpp/r_cast.h
| | +++ b/inst/include/Rcpp/r_cast.h
| | @@ -63,6 +63,7 @@ namespace Rcpp {
| |               case LGLSXP:
| |               case CPLXSXP:
| |               case INTSXP:
| | +            case NILSXP:
| |                   return Rf_coerceVector(x, RTYPE);
| |               default:
| |                   const char* fmt = "Not compatible with requested type: "
| | 
| | It will automatically coerce NULL to a declared vector type.
| | It's a more primitive solution than Nullable<T> but in many cases
| | it can be largely sufficient and make code look shorter and clearer.
| | 
| | Will it break something in established usage habits? Is it compatible with your plans for Rcpp?
| | I can prepare a PR if you decide to include it.
| 
| We could test that.  It may not do harm -- so I just turned on a rev.dep
| check for it.
| 
| Can you open an issue for it on GH though?  Better visibility and easier 'per
| concrete topic' discussion.

I am not convinced that the semantics are useful.  Your example works on the
arma type (where we our very old design issue of always returning a matrix):

> sourceCpp("/tmp/serguei.cpp")                     
> f(NULL)                                           
     [,1]                                           
> f(integer(0))                                     
     [,1]                                           
> f()
Error in f() : argument "x" is missing, with no default
> class(f(NULL))
[1] "matrix"
>

But if I do the same with Rcpp types, say a matrix via

// [[Rcpp::export]]
Rcpp::NumericMatrix g(Rcpp::NumericMatrix x) { return x+1; }

then I get more restrictive behaviour (as NumericMatrix tests for matrix)

> sourceCpp("/tmp/serguei.cpp")                     
> g(NULL)                                           
Error in g(NULL) : Not a matrix.                    
> g(matrix())
     [,1]                                           
[1,]   NA                                           
> g(vector())
Error in g(vector()) : Not a matrix.                
> g(integer())
Error in g(integer()) : Not a matrix.               
>  


Is this really useful, and can you not use Nullable<> instead?

Dirk

-- 
http://dirk.eddelbuettel.com | @eddelbuettel | edd at debian.org


More information about the Rcpp-devel mailing list