4

I need this for a bigger project but I think this minimal reprex explains it best. I have the following function in R:

test <- function(x = 2^(1:9)) {
    x
}
test()
#> [1]   2   4   8  16  32  64 128 256 512

This is working fine. However, I want to translate this to Rcpp using Rcpp Armadillo. I tried this using the following test.cpp file:

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace arma;

// [[Rcpp::export]]
vec test(const vec &lambda = arma::exp2(arma::linspace(1, 9, 9)))
{
    return lambda;
}

But compiling this using Rcpp::sourceCpp("functions/test.cpp") produces a warning:

Warning message: Unable to parse C++ default value 'arma::exp2(arma::linspace(1, 9, 9))' for argument lambda of function test

and the default argument does not work (calling test()).

Thanks so much in advance.

BerriJ
  • 913
  • 7
  • 18

2 Answers2

5

You cannot do that "under the contract we have here" because by exporting the signature to make it something R sees and can call, it has to conform to the signature of a .Call() from the R API, which is a C function where each argument is a SEXP.

So no C++ expressions allowed on the interface. You can move that logic inside as a second best choice.

Modified Code

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>

// [[Rcpp::export]]
arma::vec testCpp(const int s, const int e, const int n) {
    arma::vec lambda = arma::exp2(arma::linspace(s, e, n));
    return lambda;
}

/*** R
testCpp(1,9, 9)
*/

Output

> Rcpp::sourceCpp("~/git/stackoverflow/65357225/answer.cpp")

> testCpp(1,9, 9)
      [,1]
 [1,]    2
 [2,]    4
 [3,]    8
 [4,]   16
 [5,]   32
 [6,]   64
 [7,]  128
 [8,]  256
 [9,]  512
> 
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
1

I would like to add a solution in addition to Dirks answer. This is the CPP code.

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace arma;

// [[Rcpp::export]]
vec test_cpp(Rcpp::NumericVector x = Rcpp::NumericVector::create())
{
    if (x.size() == 0)
    {
        x = exp2(linspace(1, 9, 9));
    }
    return x;
}

The idea is to initialize x as an empty NumericVector by default. Inside the function, it is checked whether x is empty and if so, its value is overwritten by the desired default.

BerriJ
  • 913
  • 7
  • 18