不在搜索路径上的环境是否有父级?

Does an environment NOT on the search path have a parent?

我正在通读 Hadley Wickham's Advanced R book,目前正在阅读“环境”一章

它说除了 emptyenv 之外的每个环境都有一个父环境。我需要帮助来理解一些让我明白这一点的东西——也许我只是把它复杂化了或者误解了变量在 R 中的工作方式。

假设我定义了自己的环境:
myenv <- new.env()
现在,如果我做一个简单的 parent.env(myenv),我确实会按预期获得全局环境。

但是现在当我附加这个环境时会发生什么,导致它进入全局环境上方的搜索路径?
attach(myenv)
现在,如果我使用 search() 查看搜索路径,我可以看到 myenv.GlobalEnv 的父级。我还可以使用 parent.env(globalenv()) which returns myenv 来验证这一点。如果我运行 parent.env(parent.env(globalenv())) 然后我得到 tools:rstudio 这是有道理的。
但是 如果我尝试直接使用 parent.env(myenv) 查看 myenv 的父级,我会得到全局环境。为了获得我期望的结果 (tools:rstudio),我需要手动将我的环境转换为一个环境:parent.env(as.environment("myenv")) returns tools:rstudio.

那么哪个是正确的? myenv的父环境是什么?
我知道我可以使用 parent.env<- 更改环境的父级,但是如果我只是像上面的示例那样附加它,我不明白什么被认为是真正的父级

parent 环境是您从中定义新环境的机柜。但是,对于功能而言并非如此。如果你正在定义一个函数,parent 框架将是调用它的环境,而不是定义的(参见 help(sys.parent))。

环境 文档非常有用。

new.env returns a new (empty) environment with (by default) enclosure the parent frame.

parent.env returns the enclosing environment of its argument.

所以 parent 环境是全局环境也就不足为奇了。如果您将 myenv 分配到不同的外壳中,那就是它的 parent.

空的环境是行尾

parent.env(baseenv())
# <environment: R_EmptyEnv>

parent.env(parent.env(baseenv()))
# Error in parent.env(parent.env(baseenv())) : 
#  the empty environment has no parent

还有一些有用的东西...

If one follows the chain of enclosures found by repeatedly calling parent.env from any environment, eventually one reaches the empty environment emptyenv(), into which nothing may be assigned.

我想这也取决于搜索路径上的内容以及您是否将其附加到搜索路径。

myenv <- new.env()
attach(myenv)
sapply(search(), function(x) {
    attr(parent.env(as.environment(x)), "name")
})

其中列出了环境及其在我的搜索路径中的 parent。

$.GlobalEnv
[1] "myenv"

$myenv
[1] "package:stringi"

...
...

$`package:base`
NULL

[[12]]
<environment: R_EmptyEnv>

问题是附加 myenv 会创建 myenvcopy(并修改其 parent),所以我们现在有两个myenv 环境,它们可以是不同的。您已经在问题中表明他们有不同的 parent。在新的会话中尝试此操作以进一步表明它们是不同的:

myenv <- new.env()
myenv$x <- 1

# with the attach below we now have 2 myenv environments - 
#   the one above and the new one created in the attach below on the search path.
attach(myenv)

# this changes x in the original myenv but not the x in the copy on the search path
myenv$x <- 2  
myenv$x
## 2

# the copy of myenv on the search path still has the original value of x
as.environment("myenv")$x
## 1

查看此 blog post 了解更多信息。