在R中,如果我创建一个环境然后用于with评估该环境中的函数,则该函数通常可以访问变量.但是,如果我嵌套函数,由于某种原因,它们会超出范围.你能解释一下为什么会这样吗?
例:
使用名为的变量创建新环境 x
E = new.env();
E$x = c(1,2,3)
Run Code Online (Sandbox Code Playgroud)
使用with我可以打印这个变量:
with(E, print(x));
#[1] 1 2 3
Run Code Online (Sandbox Code Playgroud)
但是现在如果我嵌套这个函数,它就不再起作用了:
printMe = function() { print(x); }
with(E, printMe())
#Error in print(x) : object 'x' not found
Run Code Online (Sandbox Code Playgroud)
我知道我可以让它再次起作用:
printMe = function(x) { print(x); }
with(E, printMe(x))
#[1] 1 2 3
Run Code Online (Sandbox Code Playgroud)
但我不明白 - 如果with创建一个环境,为什么嵌套函数看不到x?如果你附上它可以工作:
attach(E)
printMe()
#[1] 1 2 3
Run Code Online (Sandbox Code Playgroud)
我想我只是缺少一些关于范围界定的东西,但推荐的方法是什么?或者,以另一种方式提出我的问题:为什么不能在with访问自由变量中嵌套函数?
基本上,当你使用时with,你也会这样做
printMe = function() { print(x); }
local({
x=1:3
printMe()
})
# Error in print(x) : object 'x' not found
Run Code Online (Sandbox Code Playgroud)
这也行不通.这与函数中如何解析自由变量有关.当你调用时printMe,它将寻找解决外壳本身中的变量,然后它查找定义函数的父框架(它看不到调用函数的位置).这里,printMe是在全球环境中定义的.但是,x并未在全球环境中定义.如果你这样做
printMe = function() { print(x); }
x=1:3
printMe()
# [1] 1 2 3
Run Code Online (Sandbox Code Playgroud)
那么这两个x和printMe在全球环境中定义,因此它的工作原理.您还可以更改该printMe功能的环境
environment(printMe) <- E
printMe()
# [1] 1 2 3
Run Code Online (Sandbox Code Playgroud)
或者在与with相同的环境中定义函数
with(E,{printMe <- function() {print(x)}; printMe()})
# [1] 1 2 3
Run Code Online (Sandbox Code Playgroud)
重点是,您调用函数的环境无关紧要,重要的是它们所定义的环境.
您可能想要查看有关这些属性的函数式编程的Advanced R材料.
R 是词法作用域而不是动态作用域。的环境printMe是Global Environment,因为它是在Global Environment中定义的:
environment(printMe)\n<environment: R_GlobalEnv>\nRun Code Online (Sandbox Code Playgroud)\n\n所以当你打电话时:
\n\nwith(E, printMe())\nRun Code Online (Sandbox Code Playgroud)\n\n该函数printMe尝试在本地查找x。它没有\xc2\xb4t。然后它尝试在其环境中查找x,这是全局环境,而不是的本地环境with。它再次找不到它,然后抛出错误。
为了说明这一点,请注意,如果您printMe在 inside 中定义with,则 的环境printMe将是 的本地环境with,并且它将找到x:
with(E,{\n printMe <- function() {\n print(x)\n } \n print(environment(printMe))\n printMe()\n })\n<environment: 0x29785678>\n[1] 1 2 3\nRun Code Online (Sandbox Code Playgroud)\n\nprintMe或者,您可以更改内部环境with:
with(E, {\n environment(printMe) <- environment()\n printMe()\n})\n[1] 1 2 3\nRun Code Online (Sandbox Code Playgroud)\n\n关于第二个示例,当您使用attach环境时,您正在使(即)E的对象可用于全局环境。因此,当您在这种情况下调用时,它会在全局环境中查找,并且由于已附加,因此它会找到它。这就是它起作用的原因。ExprintMexE
我曾经和你有同样的疑问,所以这个问题可能会进一步帮助你:Environments in R, mapply and get。
\n\n这也可能有帮助: Understanding lexical scoping in R
\n