首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么长度为1的向量最初是NAM(2)?

为什么长度为1的向量最初是NAM(2)?
EN

Stack Overflow用户
提问于 2014-02-26 02:19:25
回答 1查看 291关注 0票数 19

我偶然发现了这个行为:

代码语言:javascript
复制
x <- 1:5
> tracemem(x)
[1] "<0x12145b7a8>"
> "names<-"(x, letters[1:5])
a b c d e 
1 2 3 4 5 
> x
a b c d e 
1 2 3 4 5  
> y <- 1L
> tracemem(y)
[1] "<0x12587ed68>"
> "names<-"(y,letters[1])
tracemem[0x12587ed68 -> 0x12587efa8]: 
a 
1
> y
[1] 1 

当试图帮助某人figure out why时,在前一种情况下,向量的名称会被修改,但在后一种情况下,向量的名称不会被修改。

显然,长度为1的向量正在被复制,而长度为5的向量正在被原地修改:

代码语言:javascript
复制
> x <- 1:5
> y <- 1L
> .Internal(inspect(x))
@121467490 13 INTSXP g0c3 [MARK,NAM(1)] (len=5, tl=0) 1,2,3,4,5
> .Internal(inspect(y))
@1258d74d8 13 INTSXP g0c1 [NAM(2)] (len=1, tl=0) 1

为什么长度为1的向量在其命名属性递增为2的情况下开始存在?

作为对@nograpes下面评论的回应,我在OS X 10.7.5和R 3.0.2上看到了这一点。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-02-26 03:08:17

Matthew Dowle问了同样的问题,here,Peter Dalgaard这样回答:

这是件棘手的事情..。我不太确定我会做对,但让我们试一试

当你赋值一个常量时,你赋值的值已经是赋值表达式的一部分,所以如果你想修改它,你必须重复。所以z <- 1上的NAMED==2基本上是为了防止你意外地“改变了1的值”。如果不是这样的话,你可能会被像for(i in 1:2) {z <- 1; if(i==1) z[1] <- 2}这样的代码咬到。

这可能看起来很奇怪,但实际上,其基本原理与每次执行表单x <- y赋值时将NAM递增为2的原理完全相同。

As discussed here,R支持“按值调用”错觉,以避免至少一些不必要的对象复制。因此,例如,x <- y实际上只是将符号x绑定到y的值。但是,在不采取进一步预防措施的情况下这样做的危险在于,后续对x的修改也会修改y和任何其他链接到y的符号。R通过在将y的值分配(或者甚至可能分配)给另一个符号时将其标记为"linked to“(通过设置它的NAM=2)来解决这一问题。

执行x <- 1时,1或多或少只是另一个y,其值通过赋值表达式链接到符号x。只是后续修改x的值(回想一下,这只是对1的值的引用)引起的潜在危害是难以想象的。但是,像往常一样,将一个符号赋值给另一个符号时,R设置为NAM=2,并且不允许在没有实际复制的情况下进行任何修改。

x <- 1:10不同的原因(就像x <- 1:1x <- c(1)x <- seq(1)甚至x <- -1一样)是因为RHS实际上是一个函数调用,而函数调用的结果就是分配给x的内容。在这些情况下,x的值不仅仅是对其他符号的值的引用;修改x不会潜在地更改其他符号的值,因此不需要设置NAM=2

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22022772

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档