这似乎是一个基本问题,但我似乎无法在 stackoverflow 上找到答案。
我怎样才能获得以下效果:
f <- function(x = 1){x^2}
miracle(f)
[1] "x^2"
上下文是一个 Shiny 的应用程序(由 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
是否有内置功能?
最佳答案
我想根据 Roman Luštrik 的评论回答我自己的问题,邀请改进建议,而不是提高我微薄的“积分”。
Roman 建议使用我从未听说过的函数 body()。这是什么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?
它解释了如何从参数列表、主体和环境以编程方式创建函数。因此我决定构建我的函数
f
使用这 3 个原语并从 Shiny 内部调用主体 textInput
.所以我把它放在我的
global.R
中文件(小型股 g
是 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)
然后在我的
server.R
文件,我有:textInput(inputId = "inFun", label = h4("1. Enter a function:"),
value = deparse(body(gFun)))
它有效!
我正打算写
value = gBody
或类似的东西,但我的第一个成功来自 deparse(body(gFun))
,所以这就是我现在正在使用的。make.function
的使用在 global.R
中生成“静态”函数当然是矫枉过正,但我正在使用 make.function
内部其他地方 server.R
处理用户提供的参数和主体以创建新函数并绘制它们,因此这是一个非常有用的函数。谢谢罗曼:如果你自己写答案,我会接受你的。
关于返回一个函数的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21133475/