Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing many argumentes (...) by ellipsis in Rcpp

Tags:

r

rcpp

I'm trying to pass arguments in rcpp function using ... but it is not working. How to do this correctly?

NumericVector function(SEXP xR, ...){
    NumericVector x(xR);
    int lenx = x.size();
    NumericVector ret(lenx);
    for(int i=0; i < lenx; i++){
        if(x[i]<0){
            ret[i] = 0;
        }else if(x[i]>1){
            ret[i] = 1;
        }else{  
            ret[i] = anotherfunction(x[i], ...);
        }       
    }
    return ret; 
}

In current version I get this error: expected primary-expression before '...' token

like image 813
bartektartanus Avatar asked Jul 05 '14 22:07

bartektartanus


2 Answers

Rcpp11 has the concept of variable number of arguments with the Dots and NamedDots class. You'd do something like this:

#include <Rcpp11>

List force_dots( const Dots& dots ){
    List out(n) ;
    for( int i=0; i<n; i++){
        out[i] = Rcpp_eval( dots.promise(i), dots.environment(i)) ;    
    }
    return out ;
}

// [[export]]  
List dots_example(NumericVector x, Dots dots){
    int n = dots.size() ;
    List args = force_dots(dots) ;
    return args ;
}

/*** R
    dots_example(1:10, "e" )
    # [[1]]
    # [1] "e"
*/

When you use attributes::sourceCpp on this file, you get an R function that has ellipsis:

> dots_example
function(x, ...){
  res <- .Call( "sourceCpp_dots_example" , x, environment())
  res
}

This only partly answers the question, i.e. how to pass down to C++ a variable number of arguments from R.

You'd also need something similar to R's do.call for when you call the another_function function. For now you sort of have to do it manually until we find a way to implement a useful do_call

like image 171
Romain Francois Avatar answered Nov 15 '22 02:11

Romain Francois


You may be confusing the R-language construct ... with something you assume also exists in C++. And while C++ does have varargs that is not supported by Rcpp due to the interface from R. All we have is the .Call() interface

 SEXP somefunction(SEXP a, SEXP b, SEXP c, ...)

and here the ... is used in a literal sense just for the exposition: You can have 0, 1, 2, 3, ... SEXP arguments. But those you use must be fully qualified. In short, using ... results in the syntax error you see. See Section 5.9 of Writing R Extensions for details.

And as a side note, this is why we have macro-generated code in Rcpp. Now, with C++11 you can also use variadic templates in C++ code (which Rcpp11 uses to great effect in its internal code) but that of course does not alter the interface to R which is still the same .Call() interface, and hence the same constraint. Variadic templates are very nice, and open for use in your C++ code with either Rcpp or Rcpp11, but they do not change the interface to R. You need a fixed set of arguments, and can not rely on a variable number.

That said, if you just pass a List object as one of your arguments, then you can traverse it by position or name at will and check the content. That is the closest in spirit to your question.

like image 41
Dirk Eddelbuettel Avatar answered Nov 15 '22 02:11

Dirk Eddelbuettel