这似乎是一个基本问题,但我似乎无法在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
这是否有内置功能?
答案 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.function
在global.R
中生成'静态'功能当然是矫枉过正,但我在make.function
内的其他地方使用server.R
来处理用户 - 提供参数和主体来创建新函数并绘制它们,因此它是一个非常有用的函数。
谢谢罗马:如果你写下自己的答案,我会接受你的答案。