Передача многих аргументов () через многоточие в Rcpp

Я пытаюсь передать аргументы в функцию rcpp, используя... но это не работает. Как это сделать правильно?

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; 
}

В текущей версии я получаю эту ошибку: expected primary-expression before '...' token


person bartektartanus    schedule 05.07.2014    source источник


Ответы (2)


Rcpp11 имеет концепцию переменного количества аргументов с классами Dots и NamedDots. Вы бы сделали что-то вроде этого:

#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"
*/

Когда вы используете attributes::sourceCpp в этом файле, вы получаете функцию R с многоточием:

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

Это лишь частично отвечает на вопрос, т. е. как передать в C++ переменное количество аргументов из R.

Вам также понадобится что-то похожее на do.call в R, когда вы вызываете функцию another_function. Пока вам придется делать это вручную, пока мы не найдем способ реализовать полезный do_call

person Romain Francois    schedule 06.07.2014

Возможно, вы путаете конструкцию языка R ... с чем-то, что, по вашему мнению, также существует в C++. И хотя в C++ есть varargs, который не поддерживается Rcpp из-за интерфейса от R. Все, что у нас есть, это интерфейс .Call().

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

и здесь ... используется в буквальном смысле только для пояснения: у вас может быть 0, 1, 2, 3, ... SEXP аргументов. Но те, которые вы используете, должны быть полностью квалифицированы. Короче говоря, использование ... приводит к синтаксической ошибке, которую вы видите. См. Раздел 5.9 документа Написание расширений R для подробностей.

И в качестве примечания, именно поэтому у нас есть код, сгенерированный макросами, в Rcpp. Теперь, с C++11, вы также можете использовать вариативные шаблоны в коде C++ (которые Rcpp11 очень эффективно использует в своем внутреннем коде), но это, конечно, не меняет интерфейс на R, который остается тем же интерфейсом .Call(), и, следовательно, такое же ограничение. Шаблоны Variadic очень хороши и открыты для использования в вашем коде C++ либо с Rcpp, либо с Rcpp11, но они не меняют интерфейс на R. Вам нужен фиксированный набор аргументов, и вы не можете полагаться на число переменных.

Тем не менее, если вы просто передаете объект List в качестве одного из ваших аргументов, вы можете по желанию пройти его по положению или имени и проверить содержимое. Это наиболее близко по духу к вашему вопросу.

person Dirk Eddelbuettel    schedule 05.07.2014