user26665
user26665

Reputation: 335

Casting a String Into a Function in R

I have a Shiny app in R where I want users to be able to create functions on the fly by entering text in a text box. To enable this functionality, I would like to know the following:

How would I go about casting a string object containing a function definition into an actual function, binding it to a variable name?

For example:

function_code = 'function(x) { as.dist(1-cor(t(x))) }'
f = something(function_code, ...)

Where something() converts function_code into an actual function and assigns it to variable f. I don't think I can cast function_code into a function directly, and I've tried using as.function and that didn't work either.

Thanks!

Upvotes: 3

Views: 115

Answers (3)

IRTFM
IRTFM

Reputation: 263499

That's basically the function of the source function.

f <- source(textConnection(function_code))$value
#--------
> f
function(x) { as.dist(1-cor(t(x))) }

Upvotes: 2

Rorschach
Rorschach

Reputation: 32466

You could try

input <- list()
input$f <- "x^2 + 2"
f <- function(x) eval(parse(text = input$f)) # text to function
f(2)
# [1] 6

This way your user doesn't need to write the function(x) part. When you do this kind of thing though, your program is vulnerable in case a user adds in system calls (system).

Upvotes: 2

Gavin Simpson
Gavin Simpson

Reputation: 174968

You can use parse() and eval():

foo <- eval(parse(text = function_code))

> foo
function(x) { as.dist(1-cor(t(x))) }

Just wrap that in a function:

parseEval <- function(text) {
  eval(parse(text = text))
}

If you need an actual something() rather than a direct call.

Here's an example:

set.seed(1)
x <- matrix(runif(20), ncol = 2)
out <- foo(x)

Giving

> zapsmall(out)
   1 2 3 4 5 6 7 8 9
2  0                
3  2 2              
4  0 0 2            
5  2 2 0 2          
6  0 0 2 0 2        
7  0 0 2 0 2 0      
8  2 2 0 2 0 2 2    
9  0 0 2 0 2 0 0 2  
10 2 2 0 2 0 2 2 0 2

Upvotes: 4

Related Questions