curve3d找不到本地函数"fn"

Jar*_*fto 11 r scoping

我正在尝试使用-package中的curve3d函数emdbook来创建在另一个函数内部本地定义的函数的等高线图,如以下最小示例所示:

library(emdbook)
testcurve3d <- function(a) {
  fn <- function(x,y) {
    x*y*a
  }
  curve3d(fn(x,y))
}
Run Code Online (Sandbox Code Playgroud)

出乎意料的是,这会产生错误

> testcurve3d(2)
 Error in fn(x, y) : could not find function "fn" 
Run Code Online (Sandbox Code Playgroud)

而相同的想法与-package 的更基本curve功能一起正常工作base:

testcurve <- function(a) {
  fn <- function(x) {
    x*a
  }
  curve(a*x)
}
testcurve(2)
Run Code Online (Sandbox Code Playgroud)

问题是如何curve3d重写它以使其表现如预期.

Jam*_*mes 6

您可以暂时attach将功能环境添加到搜索路径以使其工作:

testcurve3d <- function(a) {
  fn <- function(x,y) {
    x*y*a
  }
  e <- environment()
  attach(e)
  curve3d(fn(x,y))
  detach(e)
}
Run Code Online (Sandbox Code Playgroud)

分析

问题来自于以下方面curve3d:

eval(expr, envir = env, enclos = parent.frame(2))
Run Code Online (Sandbox Code Playgroud)

在这一点上,我们看起来是10帧深,并fn在中定义parent.frame(8).所以你可以编辑一行curve3d来使用它,但我不确定这是多么强大.也许parent.frame(sys.nframe()-2)可能更强大,但?sys.parent警告可能会有一些奇怪的事情发生:

严格地说,sys.parent和parent.frame引用父解释函数的上下文.因此,内部函数(可能会或可能不会设置上下文,因此可能会或可能不会出现在调用堆栈中)可能不会被计算,并且S3方法也可以做出令人惊讶的事情.

注意延迟评估的影响:这两个函数在评估它们时查看调用堆栈,而不是在它们被调用时.将调用作为函数参数传递给它们不太可能是个好主意.