返回函数的代码

时间:2014-01-15 09:26:53

标签: r parsing shiny

这似乎是一个基本问题,但我似乎无法在stackoverflow上找到答案。

如何获得以下效果:

f <- function(x = 1){x^2}
miracle(f)
[1]  "x^2"

上下文是一个闪亮的应用程序(由RStudio打包),其中我有一个textInput()函数,我提供了一个初始值x^2。虽然这有效:

textInput(inputId = "inFun", label = h4("Enter a function:"), value = "x^2")

这不是:

textInput(inputId = "inFun", label = h4("Enter a function:"), value = f)

似乎我需要在价值的rhs上使用类似“x ^ 2”的东西。

以下是我尝试过的几种变体的代表性示例:

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

这是否有内置功能?

1 个答案:

答案 0 :(得分:9)

我想根据RomanLuštrik的评论回答我自己的问题,提出改进建议,而不是提出我的微不足道的“积分”。

Roman建议使用我从未听说过的函数体()。以下是body()f所做的事情:

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

> body(f)
{
    x^2
}

大括号是不需要的,所以我进一步搜索了一下。我设法摆脱了大括号:

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

因此,上述问题回答了我自己的问题。但是有更优雅和更短的方式吗?

根据Roman的建议使用body(),我遇到了joran,hadley和其他几个给我提供模板的优秀答案:

How to create an R function programmatically?

它解释了如何从参数列表,正文和环境以编程方式创建函数。因此,我决定使用这3个原语构造我的函数f,并从闪亮的textInput内部调用正文。

所以我把它放在我的global.R文件中(小写g是全局的简写)

# 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)

然后在我的server.R文件中,我有:

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

它有效!

我打算写value = gBody或类似的东西,但我的第一次成功来自deparse(body(gFun)),所以这就是我现在正在使用的。

使用make.functionglobal.R中生成'静态'功能当然是矫枉过正,但我​​在make.function内的其他地方使用server.R来处理用户 - 提供参数和主体来创建新函数并绘制它们,因此它是一个非常有用的函数。

谢谢罗马:如果你写下自己的答案,我会接受你的答案。