2

我正在尝试创建一个环境层次结构,其中我有一个主要环境,其中包含各种其他环境,然后可以包含其他环境(等等)。

我像这样创建环境及其子项:

parentEnv <- new.env()
childEnv <- new.env(parentEnv)

我们可以看到创建了父级和子级:

> childEnv
<environment: 0x000000000e811208>
> parentEnv
<environment: 0x000000000d9e2440>

但是,然后我检查孩子的父母,它告诉我它的 R_Global。(这实际上并不令人惊讶,因为我能够直接访问它)。new.env(parent)不做我认为的事情?

> parent.env(childEnv)
<environment: R_GlobalEnv>

没关系,然后我将我孩子的父母设置为parent.env(childEnv) <- parentEnv(尽管 R 文档说这是“危险的”并且可能会被弃用,但我还是想尝试一下)。

parent.env(childEnv) <- parentEnv

> childEnv
<environment: 0x000000000e811208>
> parent.env(childEnv)
<environment: 0x000000000d9e2440>

我们现在看到孩子的父母是parentEnv!一切都应该很棒,对吧……?

> parentEnv$childEnv
NULL
> with(parentEnv, childEnv)
<environment: 0x000000000e811208>

我无法使用 $ 访问它。虽然我可以使用'with'表示法。这里发生了什么?我不明白环境在 R 中是如何工作的?

4

2 回答 2

1

回答您关于以下问题的问题: in中with的参数被忽略,并且该对象被找到,因为它属于R_GlobalEnv。您可以看到运行以下任何一项:parentEnvwith(parentEnv, childEnv)childEnv

eval(childEnv)
evalq(childEnv)
with(new.env(), childEnv)

(环境)对象所属的环境不一定是其父环境。

如果您不仅要设置孩子的父环境,还要设置他们所属的环境parentEnv,我建议这两个选项之一:

parentEnv <- new.env()
parentEnv$childEnv1 <- new.env(parent=parentEnv)
evalq(childEnv2 <- new.env(), parentEnv)

请注意,它们给出相同的结果:

parentEnv                        # <environment: 0x0000000007ec0c18>
parent.env(parentEnv$childEnv1)  # <environment: 0x0000000007ec0c18>
parent.env(parentEnv$childEnv2)  # <environment: 0x0000000007ec0c18>

编辑:我已更改localevalq,因为它们给出了相同的结果,而后者更直观。谢谢@hadley。

于 2013-09-07T23:34:47.730 回答
0

parent当您 make 时,您实际上似乎并没有传递参数childEnv。您依赖于 R 类型匹配的参数parent似乎在这里不起作用。目前(我猜)R 正在将您的环境与hash参数进行位置匹配,并且因为它不合逻辑,所以它会默默地放弃它。而是试试这个:

parentEnv <- new.env()
childEnv <- new.env( parent = parentEnv )

parentEnv
#<environment: 0x1078dde60>
parent.env( childEnv )
#<environment: 0x1078dde60>

我认为它没有像你在你的 OP 中那样工作的事实与它new.env()是一个.Primitive函数的事实有关。从帮助手册?.Primitive

.Primitiveover函数的优点.Internal是参数传递的潜在效率,并且可以在需要的地方使用位置匹配,例如在switch. 有关详细信息,请参阅“<em>R 内部手册”</p>

于 2013-09-07T21:13:21.967 回答