do.call和curve无法在另一个函数环境中绘制函数

时间:2013-01-12 09:59:18

标签: r curve do.call

我面临一个关于 do.call 曲线的奇怪问题:

func1 <- function (m, n) {
  charac <- paste ("func2 <- function(x)", m, "*x^", n, sep = "")
  eval(parse(text = charac))
  return(func2)
}
func3 <- function (m, n) {
  my.func <- func1 (m, n)
  do.call("curve",list(expr = substitute(my.func)))
}

func1 构造 func2 func3 绘制构建的 func2 。 但是当我运行 func3 时,会显示以下错误:

> func3 (3, 6)
Error in curve(expr = function (x)  : 
  'expr' must be a function, or a call or an expression containing 'x'

但是,当我运行 func1 并手动绘制输出(不应用 func3 )时,会绘制 func2

my.func <- func1 (3, 6)
do.call("curve",list(expr = substitute(my.func)))

这里发生的事情让我感到困惑,我不知道为什么 do.call 无法在 func3 本地环境中绘制 func2

谢谢

4 个答案:

答案 0 :(得分:3)

你使这个过于复杂 - 在创建f2时你不需要做任何特别的事情:

f1 <- function (m, n) {
  function(x) m * x ^ n
}
f3 <- function (m, n) {
  f2 <- f1(m, n)
  curve(f2)
}
f3(3, 6)

当然,通过取消f1

,可以更加简洁
f4 <- function (m, n) {
  f2 <- function(x) m * x ^ n
  curve(f2)
}
f4(3, 6)

您可以在https://github.com/hadley/devtools/wiki/Functions

找到有关R的范围规则的更多信息(这使得这项工作成为可能)

答案 1 :(得分:1)

这不是do.call的问题,而是substitute 在全局环境中默认评估的问题。 所以你需要告诉它必须在哪个环境替换。这显然在func3的本地环境中。

这应该有效:

 do.call("curve",list(expr = substitute(my.func,
                                           env = parent.frame())))

编辑感谢Dwin

如评论中所述,替换env默认为当前评估环境。那么为什么下面的代码有效呢?答案在substitute

的帮助下
  

函数的形式参数或使用显式创建   delayedAssign(),promise的表达式槽替换了   符号。如果它是普通变量,则其值被替换,   除非env是.GlobalEnv,否则符号保持不变。

env = parent.frame(n=1)相当于.GlobalEnv,这就是为什么符号(my.func)保持不变。所以正确的答案是:

do.call("curve",list(expr = substitute(my.func,
                                               env = .GlobalEnv)))

要测试,我打开新的R会话:

func1 <- function (m, n) {
  charac <- paste ("func2 <- function(x)", m, "*x^", n, sep = "")
  eval(parse(text = charac))
  return(func2)
}
func3 <- function (m, n) {
  my.func <- func1 (m, n)

  do.call("curve",list(expr = substitute(my.func,env = .GlobalEnv)))
}

比我打电话

 func3(2,6)

答案 2 :(得分:1)

这有效:

func3 <- function (m, n) {
   my.func <- func1 (m, n); print(str(my.func))
   do.call(curve, list(expr=bquote( my.func) ) )
 }

答案 3 :(得分:-2)

您只需要删除行:

my.func&lt; - func1(m,n)

来自func3。