问题描述
我不明白为什么该代码在最后一行打印失败:
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
.第二条打印语句显示,由于inherits = TRUE
,在parent.frame(2)
中找到了v
.最后一个是谜.
似乎apply
忽略了get(envir = parent.frame())
.我将此追溯到apply()
中的函数forceAndCall()
.我是否缺少某些东西或这是一个错误?
在实际应用中,v
仅在函数f
的调用环境中定义(即在parent.frame()
或更高版本中),而从未在parent.env()
中定义.
此处的关键问题是调用环境以及get(inherits=TRUE)
处理它们的方式.对于初学者,我建议您阅读Hadley的函数环境.
更具体地说,人们必须了解函数的封装和调用环境,以了解发生了什么事情.
v
是在函数f
调用环境中定义的-从函数的执行环境来看-第一个print语句中的parent.frame(1L)
和最后两个打印语句中的parent.frame(2L)
./p>
我认为,如果为envir=parent.frame(1L)
提供inherits=TRUE
,则get
函数将遍历parent.frame()
层次结构并最终在父调用环境之一中找到v
.它不是.实际上,它从一个提供的envir
环境开始,并在父封闭的环境中查找v
.对于第二个print语句,parent.frame(1L)
的封闭父环境正是在其中定义v
的位置,但是在最后一个print语句中,parent.frame(1L)
的封闭父环境是base
命名空间,其中定义了apply
.最重要的是封闭父环境的是全局环境.因此未找到v
.
我们真正需要的是一个get
函数,该函数不会在父包围环境的层次结构中搜索v
,而是在父调用环境的层次结构中进行搜索.而这正是dynget()
的作用.
此函数将遍历父调用环境sys.parents()
和sys.frame()
,并在每个环境中查找v
.因此f <- function(x) dynGet('v', inherits = TRUE)
解决了这个问题.
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()
with:
Error in get("v", envir = parent.frame(), inherits = TRUE) :
object 'v' not found
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.
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?
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()
.
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
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.
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.
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.
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()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!