我正在尝试创建一个环境层次结构,其中我有一个主要环境,其中包含可能包含其他环境的各种其他环境(等等)。
我创建环境及其子代如下:
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环境如何运作?
答案 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手册”