2

我面临一个关于do.callcurve的奇怪问题:

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构造func2func3绘制构造的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

4 回答 4

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 的范围规则(使这项工作有效)的更多信息

于 2013-01-12T17:24:01.943 回答
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)
于 2013-01-12T10:53:53.687 回答
1

这有效:

func3 <- function (m, n) {
   my.func <- func1 (m, n); print(str(my.func))
   do.call(curve, list(expr=bquote( my.func) ) )
 }
于 2013-01-12T11:26:41.143 回答
-2

您只需要删除行:

my.func <- func1 (m, n)

来自 func3。

于 2013-01-12T14:45:07.843 回答