Function `[<-` will _replace_ an element, but not append an _element_

纵然是瞬间 提交于 2019-12-05 04:12:49
Matthew Lundberg

The function '[<-' might not replace anything in its first argument. In certain circumstances, it makes a copy of the object and modifies that.

See section 3.4.4 of the language definition:

x[3:5] <- 13:15

The result of this commands is as if the following had been executed

‘*tmp*‘ <- x
x <- "[<-"(‘*tmp*‘, 3:5, value=13:15)
rm(‘*tmp*‘)

This is essentially what will be run if the structure of x must be modified. However, it is clear based on experiments of the OP (and others, including myself) that the "[<-" function can modify elements in-place. Clearly nothing can be done in-place if the entire object is going to be replaced.

In-place substitution:

> x <- 1:2
> class(x)
[1] "integer"
> `[<-`(x, 2, 99L)
[1]  1 99
> x
[1]  1 99

Replacement of the entire object because the type has been changed (in the C function SubAssignTypeFix):

> x <- 1:2
> class(x)
[1] "integer"
> x[2] <- 99
> class(x)
[1] "numeric"

Another situation where the object is replaced, is when there is more than one reference to the object being modified:

x <- 1:2
y <- x
`[<-`(x, 2, 99L)
## [1]  1 99
x
## [1] 1 2

Running R under the debugger shows that the assignment function called indirectly via x[2] <- 99 invokes the C function do_set, whereas this function is not called when the assignment function is called directly by name.

do_set calls a function defineVar which modifies the appropriate environment. In the case of an in-place replacement, the object replaces itself in the environment, which are the exact cases where calling the assignment function by name results in the object being modified (a copy was not taken).

Interesting tidbit (and see here: R object identity)

#### R console:
x <- 1:2
.Internal(inspect(x))
## @26b27a8 13 INTSXP g0c1 [NAM(1)] (len=2, tl=0) 1,2
x[2] <- 99

#### gdb:
Breakpoint 7, do_set (call=0x2773640, op=0x169e668, args=0x2773870, rho=0x16c6b68) at eval.c:1732   
(gdb) p s
## $135 = (SEXP) 0x192bee0
c

#### R console:
.Internal(inspect(x))
## @192bee0 14 REALSXP g0c2 [NAM(1)] (len=2, tl=0) 1,99

To directly answer the original question, when [<- enlarges the vector, a copy is made. From the function EnlargeVector at subassign.c:113:

PROTECT(newx = allocVector(TYPEOF(x), newlen));

/* Copy the elements into place. */
...

This is R 2.15.2, which I built from source without optimization and with debugging info. It is very slow without optimization.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!