问题描述
我不明白为什么这段代码在最后一行打印失败:
I don't understand why this code is failing on the last printed line:
f <- function(x) get('v', envir = parent.frame(), inherits = TRUE)
run <- function() {
v <- 'test variable'
print(f())
print((function() f())())
print(apply(X = data.frame(1:2), MARGIN = 1, f))
}
run()
与:
Error in get("v", envir = parent.frame(), inherits = TRUE) :
object 'v' not found
第一条打印语句显示在parent.frame(1)
中找到了v
.第二个打印语句显示 v
由于 inherits = TRUE
而在 parent.frame(2)
中找到.最后一个是谜.
The first print statement shows that v
is found in parent.frame(1)
. The second print statement shows that v
is found in parent.frame(2)
due to inherits = TRUE
. The last one is the enigma.
似乎 apply
忽略了 get(envir = parent.frame())
.我将其追溯到 apply()
中的 forceAndCall()
函数.我错过了什么还是这是一个错误?
Seems that apply
is ignoring the get(envir = parent.frame())
. I traced this back to function forceAndCall()
within apply()
. Am I missing something or is this a bug?
在实际应用中,v
只定义在函数f
的调用环境中(即parent.frame()
或以上)),但永远不会在 parent.env()
中.
In real application, v
is only defined in the calling environment of the function f
(i.e. in parent.frame()
or above), but never in parent.env()
.
推荐答案
这里的关键问题是调用环境以及 get(inherits=TRUE)
处理它们的方式.首先,我建议您阅读 Hadley 的函数环境.
The key issue here are the calling environments and the way get(inherits=TRUE)
handles them. For starters, I suggest one reads Hadley's Function environments.
更具体地说,必须了解函数的封闭和调用环境才能了解正在发生的事情.
More specifically, one has to understand function's enclosing and calling environments to understand what is going on.
v
定义在函数f
的调用环境中,也就是——从函数的执行环境来看——parent.frame(1L)
在第一个打印语句中,parent.frame(2L)
在最后两个打印语句中.
v
is defined in the function f
calling environment, which is -- looking from the function's execution environment -- parent.frame(1L)
in the first print statement, and parent.frame(2L)
in the last two print statements.
我认为如果我提供带有 inherits=TRUE
的 envir=parent.frame(1L)
,get
函数将遍历 envir=parent.frame(1L)
code>parent.frame() 层次结构并最终在父调用环境之一中找到v
.它不是.实际上,它从一个提供的 envir
环境开始,并在 v
的父 封闭 环境中查找.对于第二条print语句,parent.frame(1L)
的封闭父环境正是定义了v
的地方,但是在最后一条print语句中,封闭父环境是v
parent.frame(1L)
是 base
命名空间,其中定义了 apply
.在此之上的封闭父环境是全局环境.所以 v
没有找到.
I thought that if I supply envir=parent.frame(1L)
with inherits=TRUE
, the get
function would traverse the parent.frame()
hierarchy and eventually find v
in one of the parent calling environments. It does not. In reality it starts from the envir
environment one supplies and looks in the parent enclosing environments for v
. For the second print statement, the enclosing parent environment of parent.frame(1L)
is exactly where v
is defined, but in the last print statement, the enclosing parent environment of parent.frame(1L)
is the base
namespace where apply
is defined. Enclosing parent environment on top of that is the global environment. So v
is not found.
我们真正需要的是一个 get
函数,它不会在父封闭环境层次结构中搜索 v
,而是在父调用环境层次结构中搜索.而这正是 dynget()
所做的.
What we really need is a get
function that doesn't search in the parent enclosing environments hierarchy for v
, but in parent calling environments hierarchy. And that is exactly what dynget()
does.
dynGet() 有点实验性,可以在另一个内部使用功能.它在调用者中寻找一个对象,即sys.frame()s 的函数.谨慎使用
此函数将遍历父调用环境sys.parents()
和sys.frame()
并在每个环境中查找v
他们.所以 f <- function(x) dynGet('v', inherits = TRUE)
解决了这个问题.
This function will traverse the parent calling environments sys.parents()
with sys.frame()
and look for v
in each of them. So f <- function(x) dynGet('v', inherits = TRUE)
solves the problem.
这篇关于apply() 和 forceAndCall() 忽略来自 parent.frame() 的 get()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!