2014-02-25 31 views
18

我偶然发现了这种行为:为什么最初在NAM(2)的长度为1的矢量?

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 outwhy时,但后者并非如此。

显然,长度的一个矢量被复制,而长度5向量来代替被修改:

> 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 

为什么长度的一个矢量开始了它的存在与递增到2其命名属性?

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

+0

那么,除了作者可能的假设,标量永远不会得到一个名称分配... –

+0

在Windows中,我不能重复这一点:矢量'x'的名称是*不*修改地点。 – nograpes

+1

@nograpes情节变厚。我添加了我的操作系统和R版本的问题。我觉得奇怪的是,操作系统之间会存在差异... – joran

回答

18

马修Dowle问同样的问题here,彼得达尔加德正是如此回答:

这是棘手的事......我不是很肯定,我会得到它的权利,但 让我们尝试

当您分配常量时,您分配的值已经是 分配表达式的一部分,因此如果要修改它,则必须复制 。所以NAMED==2z <- 1基本上是为了防止你从 不小心“改变1的值”。如果不是,那么你可以用这样的代码来咬 。

这似乎是异国情调,但真正的理由是完全一样的,因为它是递增NAM2每当做形式x <- y的分配。

As discussed here,R支持“按价值调用”错觉,以避免至少一些不必要的对象复制。因此,例如,x <- y确实只是将符号x绑定到y的值。但是,如果没有进一步的预防措施,这样做的危险是,x的后续修改也会修改y和链接到y的任何其他符号。 R通过将y的值标记为“链接到”(通过将其设置为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

+0

我想我可能只是勉强按照这个。你能详细说明他所暗示的可能会出现什么问题吗?我想我明白了,但似乎真的太疯狂了。 – joran

+2

Peter是否暗示如果没有这个,'z [1] < - 2'实际上可以将'1'的值改为'2'?由于循环中的第一个赋值,'1'与'z'紧密相连? –

+2

@GavinSimpson是的。我将编辑我的答案,旨在澄清并回答乔兰的质疑。 –

相关问题