Kon*_*lph 17 environment r list assign
[[<- 在非本地对象上使用时,列表和环境的行为会有所不同:
lst = list()
env = new.env()
(function () lst[['x']] = 1)()
(function () env[['x']] = 1)()
Run Code Online (Sandbox Code Playgroud)
lst
# list()
as.list(env)
# $x
# [1] 1
Run Code Online (Sandbox Code Playgroud)
换句话说,如果目标[[<-是环境,它会修改(非本地)环境,但如果它是矢量/列表,则会创建一个新的本地对象.
我想知道两件事:
<<-?关于(1),我知道列表和环境之间存在多种差异(特别是我知道环境不会被复制)但文档中没有提到为什么[[<-两者之间的语义不同 - 特别是为什么运营商将在不同的范围内运作.这是一个错误吗?至少它是反直觉的,并且需要一些非平凡的实现恶作剧.1
关于(2),显而易见的解决方案当然是使用<<-:
(function () lst[['x']] <<- 1)()
Run Code Online (Sandbox Code Playgroud)
但是,我更喜欢严格理解差异,而不是仅仅解决它们.此外,我到目前为止使用assign而不是,<<-我更喜欢这个,因为它允许我更好地控制作业的范围(特别是因为我可以指定inherits = FALSE.<<-对我来说太多伏都教了.
但是,上述内容无法解决(据我所知)使用,assign因为assign只适用于环境,而不是列表.特别是,虽然assign('x', 1, env)工作(并且与上面相同),assign('x', 1, lst)但是不起作用.
1
为了详细说明,当然希望R使用动态调度(例如通过S3)对不同的对象类型做不同的事情.但是,这不是这种情况(至少不是直接):范围解析的区别发生在已知分配目标的对象类型之前 - 否则上述操作将在全局操作lst,而不是创建新的本地对象.所以内部[[<-必须做相当于:
`[[<-` = function (x, i, value) {
if (exists(x, mode = 'environment', inherits = TRUE))
assign(i, value, pos = x, inherits = FALSE)
else if (exists(x, inherits = FALSE)
internal_assign(x, i, value)
else
assign(x, list(i = value), pos = parent.frame(), inherits = FALSE)
}
Run Code Online (Sandbox Code Playgroud)
在R-语言定义(第2.1.10)说:
与大多数其他R对象不同,环境在传递给函数或在赋值中使用时不会被复制.
"6.3关于评估的更多内容"部分也给出了一个略微相关的提示:
请注意,给定环境中的评估实际上可能会改变该环境,最明显的是涉及赋值运算符的情况,例如
Run Code Online (Sandbox Code Playgroud)eval(quote(total <- 0), environment(robert$balance)) # rob Rob在列表中进行评估时也是如此,但原始列表不会更改,因为一个人正在处理副本.
因此,您的第一个问题的答案是需要复制列表以分配给它们,但可以适当地修改环境(这具有巨大的性能影响).
关于你的第二个问题:
如果您正在使用列表,唯一的选择似乎是
get),assign将修改后的列表复制回原始环境.| 归档时间: |
|
| 查看次数: |
149 次 |
| 最近记录: |