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

#r #rcpp

#r #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

Ответ №1:

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

 #include <Rcpp11>

List force_dots( const Dotsamp; 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.

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

Ответ №2:

Возможно, вы путаете конструкцию на языке 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() интерфейсом и, следовательно, тем же ограничением. Вариационные шаблоны очень хороши и открыты для использования в вашем коде C либо с Rcpp, либо с Rcpp11, но они не меняют интерфейс на R. Вам нужен фиксированный набор аргументов, и вы не можете полагаться на переменное число.

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