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

感情迁移 提交于 2020-01-02 02:00:43

问题


I noticed the following when using '[<-'. I am successful at replacing elements but not at appending an element to the vector.

Example:

VarX <- integer()
VarX[1] <- 11
`[<-`(VarX, 2, 22)
VarX
# [1] 11

# Expected the value of VarX to be:  
# [1] 11 22

# Also tried: 
`[<-`(VarX, i=2, value=22)
VarX 
# [1] 11

However, if there is already a value at the index, the value does get replaced.

VarX <- integer()
VarX[1] <- 11
VarX[2] <- 99
VarX
# [1] 11 99
`[<-`(VarX, 2, 22)
VarX
# [1] 11 22

Do I simply have the syntax wrong, or is this as intended? Any further insight into what is going on here would be appreciated.

Please note, there is no concrete objective here other than to better understand the language.

Update regarding @Roland and @Dason 's comments.

It appears that the behavior is tied to how the values of the object are initially assigned. For example, when the value assigned to VarX is 1:2 versus c(1, 2) the behavior of [<-(VarX, 2, 22) gives different results, as shown below:

### changes not saved to VarX

rm(VarX)  # actually ran:     rm(list=ls(all=TRUE))
VarX <- 1:2
VarX
# [1] 1 2

`[<-`(VarX, 2, 22)
# [1]  1 22

VarX
# [1] 1 2

### changes ARE saved to VarX

rm(VarX)  # actually ran:     rm(list=ls(all=TRUE))
VarX <- c(1, 2)
VarX[2] <- 2
VarX
# [1] 1 2

`[<-`(VarX, 2, 22)
# [1]  1 22

VarX
# [1]  1 22



> sessionInfo()
R version 2.15.1 (2012-06-22)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base  

回答1:


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.



来源:https://stackoverflow.com/questions/15178507/function-will-replace-an-element-but-not-append-an-element

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