curve3d 找不到局部函数 "fn"
curve3d can't find local function "fn"
我正在尝试使用 emdbook
包中的 curve3d
函数来创建在另一个函数内局部定义的函数的等值线图,如以下最小示例所示:
library(emdbook)
testcurve3d <- function(a) {
fn <- function(x,y) {
x*y*a
}
curve3d(fn(x,y))
}
没想到,这会产生错误
> testcurve3d(2)
Error in fn(x, y) : could not find function "fn"
而同样的想法适用于 base
-package 的更基本的 curve
功能:
testcurve <- function(a) {
fn <- function(x) {
x*a
}
curve(a*x)
}
testcurve(2)
问题是如何重写 curve3d
以使其按预期运行。
eval - parse 解决方案绕过了对变量范围的一些担忧。这直接传递变量和函数的值,而不是传递变量或函数名称。
library(emdbook)
testcurve3d <- function(a) {
fn <- eval(parse(text = paste0(
"function(x, y) {",
"x*y*", a,
"}"
)))
eval(parse(text = paste0(
"curve3d(", deparse(fn)[3], ")"
)))
}
testcurve3d(2)
我找到了其他我不太喜欢的解决方案,但也许它会对你有所帮助。
您可以创建函数 fn
how a call
object 并在 curve3d
中对其求值:
fn <- quote((function(x, y) {x*y*a})(x, y))
eval(call("curve3d", fn))
另一个函数内部,存在连续问题,a
必须在全局环境中,但可以用substitute
修复。
示例:
testcurve3d <- function(a) {
fn <- substitute((function(x, y) {
c <- cos(a*pi*x)
s <- sin(a*pi*y/3)
return(c + s)
})(x, y), list(a = a))
eval(call("curve3d", fn, zlab = "fn"))
}
par(mfrow = c(1, 2))
testcurve3d(2)
testcurve3d(5)
您可以暂时attach
将功能环境添加到搜索路径以使其工作:
testcurve3d <- function(a) {
fn <- function(x,y) {
x*y*a
}
e <- environment()
attach(e)
curve3d(fn(x,y))
detach(e)
}
分析
问题出在curve3d
中的这一行:
eval(expr, envir = env, enclos = parent.frame(2))
此时,我们似乎有10帧深度,fn
定义在parent.frame(8)
中。因此,您可以编辑 curve3d
中的行来使用它,但我不确定它有多稳健。也许 parent.frame(sys.nframe()-2)
可能更健壮,但正如 ?sys.parent
警告的那样,可能会发生一些奇怪的事情:
Strictly, sys.parent and parent.frame refer to the context of the
parent interpreted function. So internal functions (which may or may
not set contexts and so may or may not appear on the call stack) may
not be counted, and S3 methods can also do surprising things.
Beware of the effect of lazy evaluation: these two functions look at
the call stack at the time they are evaluated, not at the time they
are called. Passing calls to them as function arguments is unlikely to
be a good idea.
我正在尝试使用 emdbook
包中的 curve3d
函数来创建在另一个函数内局部定义的函数的等值线图,如以下最小示例所示:
library(emdbook)
testcurve3d <- function(a) {
fn <- function(x,y) {
x*y*a
}
curve3d(fn(x,y))
}
没想到,这会产生错误
> testcurve3d(2)
Error in fn(x, y) : could not find function "fn"
而同样的想法适用于 base
-package 的更基本的 curve
功能:
testcurve <- function(a) {
fn <- function(x) {
x*a
}
curve(a*x)
}
testcurve(2)
问题是如何重写 curve3d
以使其按预期运行。
eval - parse 解决方案绕过了对变量范围的一些担忧。这直接传递变量和函数的值,而不是传递变量或函数名称。
library(emdbook)
testcurve3d <- function(a) {
fn <- eval(parse(text = paste0(
"function(x, y) {",
"x*y*", a,
"}"
)))
eval(parse(text = paste0(
"curve3d(", deparse(fn)[3], ")"
)))
}
testcurve3d(2)
我找到了其他我不太喜欢的解决方案,但也许它会对你有所帮助。
您可以创建函数 fn
how a call
object 并在 curve3d
中对其求值:
fn <- quote((function(x, y) {x*y*a})(x, y))
eval(call("curve3d", fn))
另一个函数内部,存在连续问题,a
必须在全局环境中,但可以用substitute
修复。
示例:
testcurve3d <- function(a) {
fn <- substitute((function(x, y) {
c <- cos(a*pi*x)
s <- sin(a*pi*y/3)
return(c + s)
})(x, y), list(a = a))
eval(call("curve3d", fn, zlab = "fn"))
}
par(mfrow = c(1, 2))
testcurve3d(2)
testcurve3d(5)
您可以暂时attach
将功能环境添加到搜索路径以使其工作:
testcurve3d <- function(a) {
fn <- function(x,y) {
x*y*a
}
e <- environment()
attach(e)
curve3d(fn(x,y))
detach(e)
}
分析
问题出在curve3d
中的这一行:
eval(expr, envir = env, enclos = parent.frame(2))
此时,我们似乎有10帧深度,fn
定义在parent.frame(8)
中。因此,您可以编辑 curve3d
中的行来使用它,但我不确定它有多稳健。也许 parent.frame(sys.nframe()-2)
可能更健壮,但正如 ?sys.parent
警告的那样,可能会发生一些奇怪的事情:
Strictly, sys.parent and parent.frame refer to the context of the parent interpreted function. So internal functions (which may or may not set contexts and so may or may not appear on the call stack) may not be counted, and S3 methods can also do surprising things.
Beware of the effect of lazy evaluation: these two functions look at the call stack at the time they are evaluated, not at the time they are called. Passing calls to them as function arguments is unlikely to be a good idea.