Reputation: 335
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
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
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
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