Hello, Doing typeof() on an object appears to reset the "named" field in its sxpinfo header to 2, which can change the way that subsequent subassignment operations are carried out: X <- 1:5e7 .Internal(inspect(X)) # @4eeb0008 13 INTSXP g0c7 [NAM(1)] (len=50000000, tl=0) 1,2,3,4,5,... system.time(X[1] <- 9L) # user system elapsed # 0 0 0 typeof(X) .Internal(inspect(X)) # @4eeb0008 13 INTSXP g1c7 [MARK,NAM(2)] (len=50000000, tl=0) 9,2,3,4,5,... system.time(X[2] <- 9L) # user system elapsed # 0.16 0.08 0.23 Some other functions that query the nature of an object (e.g. class(), length(), attributes()) do not modify the object's "named" field. Is there a reason that typeof() should? (Possibly of interest is this somewhat related thread on Stack Overflow: http://stackoverflow.com/questions/15559387/operator-in-rstudio-and-r/15559956#15559956 ).
Why does typeof() modify an object's "named" field?
2 messages · Josh O'Brien, R. Michael Weylandt
On Fri, Mar 22, 2013 at 7:43 PM, Josh O'Brien <joshmobrien at gmail.com> wrote:
Some other functions that query the nature of an object (e.g. class(), length(), attributes()) do not modify the object's "named" field. Is there a reason that typeof() should?
Because it's not implemented as a primitive and the closure used in setting up the internal call [1] bumps up the NAMED field: compare x <- 1:3; y <- 1:4; z <- 1:5 .Internal(inspect(x)) typeof(x) # Closure .Internal(inspect(x)) .Internal(inspect(y)) class(y) # Primitive .Internal(inspect(y)) .Internal(inspect(z)) .Internal(typeof(z)) .Internal(inspect(z)) giving
x <- 1:3; y <- 1:4; z <- 1:5 .Internal(inspect(x))
@7886c78 13 INTSXP g0c2 [NAM(1)] (len=3, tl=0) 1,2,3
typeof(x) # Closure
[1] "integer"
.Internal(inspect(x))
@7886c78 13 INTSXP g0c2 [NAM(2)] (len=3, tl=0) 1,2,3
.Internal(inspect(y))
@7886cf0 13 INTSXP g0c2 [NAM(1)] (len=4, tl=0) 1,2,3,4
class(y) # Primitive
[1] "integer"
.Internal(inspect(y))
@7886cf0 13 INTSXP g0c2 [NAM(1)] (len=4, tl=0) 1,2,3,4
.Internal(inspect(z))
@7a8e9d8 13 INTSXP g0c3 [NAM(1)] (len=5, tl=0) 1,2,3,4,5
.Internal(typeof(z))
[1] "integer"
.Internal(inspect(z))
@7a8e9d8 13 INTSXP g0c3 [NAM(1)] (len=5, tl=0) 1,2,3,4,5 Michael [1] I'm not super certain about the fact it's the closure vs argument passing (or if the distinction even makes sense) but I know that this behavior is part of the reason primitives are important.