Search code examples
revallazy-evaluationvariadic-functionsvariadic

How to cast a character string as a function (e.g., using `as.function`)?


I have a character string:

FUN.n = "exp( 3 * x^2 + 2 * x + 1)";

I want to cast it as a function:

myFunction = castAsFunction ( FUN.n );

So that I can access it like:

myFunction(x)

and it will evaluate appropriately.

FUN.n = "exp( 3 * x^2 + 2 * x + 1)";
myFunction = castAsFunction (  FUN.n );

# [...]
myFunction = function(x)
    {
    exp( 3 * x^2 + 2 * x + 1);
    }

x = -3:3;

myFunction(x);

# [1] 3.6e+09 8.1e+03 7.4e+00 2.7e+00 4.0e+02 2.4e+07 5.8e+14

I have tried as.function and eval(parse(text and none of them behave as I would expect.

I am looking for a variadic solution.


Solution

  • We could actually create a function called castAsFunction. We would need to give it not only a string as function body, but also the formal arguments. It feels like the function could be simplified, but it works with the example above.

    FUN.n = "exp( 3 * x^2 + 2 * x + 1)"
    x = -3:3
    
    castAsFunction <- function(body, ...) {
      dots <- match.call(expand.dots = FALSE)$... 
      form_ls <- rep(list(bquote()), length(dots))
      names(form_ls) <- as.character(dots)
      f <- function(){}
      formals(f) <- form_ls
      body(f) <- str2lang(body)
      environment(f) <- parent.frame()
      f
    }
    
    myfun <- castAsFunction(FUN.n, x)
    
    myfun
    #> function (x) 
    #> exp(3 * x^2 + 2 * x + 1)
    
    myfun(x)
    #> [1] 3.584913e+09 8.103084e+03 7.389056e+00 2.718282e+00 4.034288e+02
    #> [6] 2.415495e+07 5.834617e+14
    

    Created on 2021-02-18 by the reprex package (v0.3.0)