返回一个函数的代码

标签 r parsing shiny

这似乎是一个基本问题,但我似乎无法在 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/

相关文章:

python - 使用 Python BeautifulSoup 解析远程网络

ios - 如何将 userdefault 值转换为 URL?

c++ - 我可以根据 C++ 中的输入通过相同的方法返回不同的对象吗?

r - 带有 Shiny VisNetwork Graph 的搜索栏

r - 将整数顺序分配给十进制数

r - 计算和绘制任意 rasterLayer 的矢量场

r - 在 caret 包中使用 xgboost 模型时,每次运行都会产生不同的结果

R:维度名称列表中的稀疏矩阵

r - 为什么 "<<-"会扰乱 Shiny 中函数的范围

r - Shiny 元素 : Blank Spaces in inputId