Josh O'Brien
2013-Mar-22 19:43 UTC
[Rd] Why does typeof() modify an object's "named" field?
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 ).
R. Michael Weylandt
2013-Mar-23 09:43 UTC
[Rd] Why does typeof() modify an object's "named" field?
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.