3

In R the possibility exists to have a function that creates another function, e.g.

create_ax2 <-  function(a) {

  ax2 <- function(x) {
    y <- a * x^2
    return(y)
  }

  return(ax2)
}

The result of which is

> fun <- create_ax2(3)
> fun(1)
[1] 3
> fun(2)
[1] 12
> fun(2.5)
[1] 18.75

I have such a complicated create function in R which take a couple of arguments, sets some of the constants used in the returned function, does some intermediary computations etc... But the result is a function that is way too slow. Hence I tried to translate the code to C++ to use it with Rcpp. However, I can't figure out a way to construct a function inside a C++ function and return it to be used in R.

This is what I have so far:

Rcpp::Function createax2Rcpp(int a) {

  double ax2(double x) {
    return(a * pow(x, 2));
  };

  return (ax2);
}

This gives me the error 'function definition is not allowed here', I am stuck about how to create the function.

EDIT: The question RcppArmadillo pass user-defined function comes close, but as far as I can tell, it only provides a way to pass a C++ function to R. It does not provide a way to initialise some values in the C++ function before it is passed to R.

Community
  • 1
  • 1
Akkariz
  • 139
  • 8
  • This is not an Rcpp issue, C++ don't allow local function declarations. Thus, you need either to define this function outside local scope or wrap it in the class. – m0nhawk Jan 25 '16 at 14:08
  • 1
    @m0nhawk of course it does – Severin Pappadeux Jan 25 '16 at 14:09
  • @SeverinPappadeux Of course I can use `std::function` and lambdas, but you can't define them like in the code above. – m0nhawk Jan 25 '16 at 14:12
  • Possible duplicate of [RcppArmadillo pass user-defined function](http://stackoverflow.com/questions/14428687/rcpparmadillo-pass-user-defined-function) – m0nhawk Jan 25 '16 at 14:32
  • I edited with an explanation why it is different to http://stackoverflow.com/questions/14428687/rcpparmadillo-pass-user-defined-function. Could you give an example of how to construct such a function using lambdas? – Akkariz Jan 25 '16 at 14:46
  • 1
    Okay, so you want an Rcpp function that creates another Rcpp function? Why? (And think carefully why that might be challenging if a compiled language is involved.) – Roland Jan 25 '16 at 15:14
  • @m0nhawk no, he wants to have a function with a closure – Severin Pappadeux Jan 25 '16 at 15:58
  • I cannot make any sense of this question. R code is meant to be organised in package, and we support that mode pretty well. What you suggest here is ... just a wee bit unusual. Maybe time for you to re-read some of our vignettes? – Dirk Eddelbuettel Jan 25 '16 at 18:39
  • It was a question out of curiosity. I can easily circumvent the "problem" by defining a function `double ax2(double x, int a)`, but I was wondering if there was a way to fix `a` when creating the function. (My function has a lot more of those "constants" to be set). – Akkariz Jan 25 '16 at 19:41
  • If you had asked the function that way I could have pointed you to RcppDE where we used this idiom to pass an environment from R to C++. – Dirk Eddelbuettel Jan 25 '16 at 19:42
  • I will have a look at it, thanks. My bad if the question was not clear, I'm not very familiar with Rcpp (yet). – Akkariz Jan 25 '16 at 19:45

1 Answers1

2

Ok, as far as I understand, you want a function returning function with a closure, a.k.a. " the function defined in the closure 'remembers' the environment in which it was created."

In C++11 and up it is quite possible to define such function, along the lines

std::function<double(double)> createax2Rcpp(int a) {
    auto ax2 = [a](double x) {  return(double(a) * pow(x, 2)); };
    return ax2;
}

What happens, the anonymous class and object with overloaded operator() will be created, it will capture the closure and moved out of the creator function. Return will be captured into instance of std::function with type erasure etc.

But! C/C++ function in R requires to be of a certain type, which is narrower (as an opposite to wider, you could capture narrow objects into wide one, but not vice versa).

Thus, I don't know how to make from std::function a proper R function, looks like it is impossible.

Perhaps, emulation of the closure like below might help

static int __a;

double ax2(double x) {
    return(__a * pow(x, 2));
}

Rcpp::Function createax2Rcpp(int a) {
    __a = a;

    return (ax2);
}
Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64
  • Thanks. The goal was indeed to create a function which 'remembers' the environment in which it was created such that I do not need pass the extra variables (in this case `a`) around. As this seems to be impossible, I'm marking this as accepted and will directly define the function as `double ax2(double x, int a)`. – Akkariz Jan 25 '16 at 19:36