Rstudio 的行为
Rstudio 的对象浏览器修改它检查的对象,在修改时强制复制。具体来说,对象浏览器使用至少一个 R 函数,其调用在内部强制评估对象,在此过程中将对象的命名字段的值从 1 重置为 2。来自R-Internals 手册:
当一个对象即将被更改时,会查询指定的字段。值 2 表示对象必须在被更改之前被复制。[...] 值 1 用于 [...] 原则上在计算期间存在两个副本的情况 [...] 但不再存在,因此可以优化一些原始函数在这种情况下避免复制。
要查看对象浏览器修改了命名字段([NAM()]
在下一个代码块中),请比较运行以下行的结果。首先,两条“线”一起运行,因此 RstudioX
在查询其结构之前没有时间“接触”。在第二种情况下,每一行都是单独粘贴的,所以X
在检查之前进行修改。
## Pasted in together
x <- 1:10; .Internal(inspect(x))
# @46b47b8 13 INTSXP g0c4 [NAM(1)] (len=10, tl=0) 1,2,3,4,5,...
## Pasted in with some delay between lines
x <- 1:10
.Internal(inspect(x))
# @42111b8 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,...
一旦命名字段设置为 2,[<-(X, ...)
将不会修改原始对象。将以下内容一次性粘贴到 Rstudio 中会修改X
,而逐行粘贴则不会:
x <- 1:10
"[<-"(x, 1, 111)
所有这一切的另一个后果是,Rstudio 的对象浏览器实际上使某些操作比其他操作要慢。同样,比较首先粘贴在一起的相同的两个命令,然后一次一个:
## Pasted in together
x <- 1:5e7
system.time(x[1] <- 9L)
# user system elapsed
# 0 0 0
## Pasted in one at a time
x <- 1:5e7
system.time(x[1] <- 9L)
# user system elapsed
# 0.11 0.04 0.16
[<- 在 R 中的可变行为
[<-
wrt 修改向量的行为X
取决于X
分配给它的元素的存储类型和存储类型。这解释了R
的行为,但不解释 Rstudio 的行为。
在 R 中,当[<-
附加到 vectorX
或执行需要X
修改其类型的子X
赋值时,将被复制并且返回的值不会覆盖预先存在的变量X
。(为此,您需要执行类似X <- "[<-(X, 2, 100)
.
所以,以下都不修改 X
X <- 1:2 ## Note: typeof(X) --> "integer"
## Subassignment that requires that X be coerced to "numeric" type
"[<-"(X, 2, 100) ## Note: typeof(100) --> "numeric"
X
# [1] 1 2
## Appending to X
"[<-"(X, 3, 100L)
X
# [1] 1 2
不过,只要有可能,R 确实允许[<-
函数通过引用直接修改X
(即不复制)。这里的“可能”包括子分配不需要X
修改类型的情况。
所以以下所有修改 X
X <- c(0i, 0i, 0i, 0i)
"[<-"(X, 1, TRUE)
"[<-"(X, 2, 20L)
"[<-"(X, 3, 3.14)
"[<-"(X, 4, 5+5i)
X
# [1] 1.00+0i 20.00+0i 3.14+0i 5.00+5i