[Rcpp-devel] handling ellipsis (...) in attributes exposed functions
Romain Francois
romain at r-enthusiasts.com
Tue Oct 1 14:42:32 CEST 2013
Hello,
Behind the title, there is a simple idea. The ability to call a c++
function with variable number of arguments from R.
e.g we have a function "foo" defined in C++ and we want to call
foo( x, y, z )
I'd like to have the ability to define the function like this:
// [[Rcpp::export]]
void foo( Dots dots ){
// do whatever
}
and generating whatever code is necessary so that the contents of the
... is passed down ithout being evaluated (because sometimes it matters).
Dots would be a class that captures the arguments in a List and an
Environment where the arguments can be evaluated.
This is (partially) implemented in Rcpp11. It mostly happened in this
commit:
https://github.com/romainfrancois/Rcpp11/commit/813e9029be02ed6d33e1ed775253382b3b80a339
The version I've implemented handles the "data" argument specifically,
doing what you would expect. So I can do this:
#include <Rcpp.h>
using namespace Rcpp ;
// [[Rcpp::export]]
List foo( Dots dots ){
return List::create(
dots.size(),
dots.eval(0)
);
}
/*** R
local({
x <- y <- z <- rnorm(10)
foo( x, y, z )
})
foo( Sepal.Length, data = iris )
*/
There are use cases for something like this. My latest example is order_
from dplyrRcpp to support something like this:
order_( Sepal.Length, Sepal.Width, data = iris )
It is now implemented like this:
order_ <- function(..., data){
dots <- as.list( sys.call()[-1L] )
parent_frame <- parent.frame()
if( "data" %in% names(dots) ){
dots <- dots[ names(dots) != "data" ]
env <- as.environment(data)
parent.env(env) <- parent_frame
} else {
env <- parent_frame
}
order_impl( dots, env )
}
and its c++:
// [[Rcpp::export]]
IntegerVector order_impl( List args, Environment env ){
int nargs = args.size() ;
SEXP tmp ;
List variables(nargs) ;
LogicalVector ascending(nargs) ;
for(int i=0; i<nargs; i++){
tmp = args[i] ;
if( TYPEOF(tmp) == LANGSXP && CAR(tmp) == Rf_install("desc") ){
variables[i] = Rf_eval( CAR(CDR(tmp) ), env ) ;
ascending[i] = false ;
} else{
variables[i] = Rf_eval( tmp, env );
ascending[i] = true ;
}
}
OrderVisitors o(variables,ascending, nargs) ;
return o.apply() ;
}
Anyway. I just wanted to start a discussion about this. Would people
find it useful ...
Romain
--
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
More information about the Rcpp-devel
mailing list