使用父环境访问子级

时间:2013-09-07 20:50:44

标签: r

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

我创建环境及其子代如下:

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)&lt; - parentEnv

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

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

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

我无法使用$访问它。虽然我可以使用'with'符号。这里发生了什么?我不明白R环境如何运作?

2 个答案:

答案 0 :(得分:1)

回答有关with的问题:parentEnv中的参数with(parentEnv, childEnv)被忽略,找到了对象childEnv,因为属于在R_GlobalEnv中。你可以看到运行以下任何一个:

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>

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

答案 1 :(得分:0)

在制作parent时,您实际上似乎并未传递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的帮助手册:

  

.Primitive超过.Internal函数的优点是参数传递的潜在效率,并且可以在需要时使用位置匹配,例如,在switch。有关详细信息,请参阅“ R Internals手册