Return a function's code

parsing, r, shiny

Solution

I'd like to answer my own question, based on Roman Luštrik's comment, to invite suggestions for improvements rather than raising my meagre tally of "points".

Roman suggested the function body(), which I had never heard of. Here is what `body()` does to `f`:

f <- function(x = 1){x^2}

> body(f)
{
    x^2
}

The curly brackets were unwanted, so I searched a little further. I managed to get rid of the curly brackets with this:

> gsub(' {2,}','',deparse(body(f))[2])
[1] "x^2"

The above, therefore, answers my own question. But is there a more elegant and shorter way?

Following Roman's suggestion to use `body()`, I came across this outstanding answer by joran, hadley, and several others, which provided me with a template:

How to create an R function programmatically?

There it explains how to create a function programmatically from an argument list, a body and an environment. I therefore decided to construct my function `f` with these 3 primitives and to call the body from inside shiny's `textInput`.

So I put this in my `global.R` file (the small-cap `g` is shorthand for global)

# Convenience function
make.function <- function(args = alist(a = 1, b = 2), body = quote(a + b), 
                          env = parent.frame()) {
  subs <- list(args = as.pairlist(args), body = body)
  eval(substitute(`function`(args, body), subs), env)
}
gArg <- alist(a = 1, b = 2)
gBody <- quote(a + b)
gFun <- make.function(gArg, gBody)

Then in my `server.R` file, I have:

textInput(inputId = "inFun", label = h4("1. Enter a function:"), 
          value = deparse(body(gFun)))

And it works!

I was planning to write `value = gBody` or something to that effect, but my first success came with `deparse(body(gFun))`, so that's what I'm using now.

The use of `make.function` to produce a 'static' function in `global.R` is of course overkill, but I'm using `make.function` elsewhere inside `server.R` to process the user-supplied arguments and body to create new functions and plot them, so it's a very useful function to have.

Thanks Roman: if you write your own answer I'll accept yours.

Problem

This would seem to be an elementary question, but I can't seem to find an answer on stackoverflow. How can I obtain the following effect: ``` f <- function(x = 1){x^2} miracle(f) [1] "x^2" ``` The context is a shiny app (package by RStudio) in which I have a `textInput()` function to which I supply an initial value `x^2`. While this works: ``` textInput(inputId = "inFun", label = h4("Enter a function:"), value = "x^2") ``` this doesn't: ``` textInput(inputId = "inFun", label = h4("Enter a function:"), value = f) ``` It appears that I need something like "x^2" on the rhs of value. Below is a representative sample of several variations I have tried: ``` eval(parse(text = f)) Error in as.character(x) : cannot coerce type 'closure' to vector of type 'character' f(x = "x") Error in x^2 : non-numeric argument to binary operator `f` function(x){x^2} f(x = `x`) Error in f(x = x) : object 'x' not found ``` Is there a built-in function for this?

Original source

Related problems