On Nov 24, 2011, at 12:34 , Matthew Dowle wrote:
On Nov 24, 2011, at 11:13 , Matthew Dowle wrote:
Hi,
I expected NAMED to be 1 in all these three cases. It is for one of
them,
but not the other two?
R version 2.14.0 (2011-10-31)
Platform: i386-pc-mingw32/i386 (32-bit)
x = 1L
.Internal(inspect(x)) # why NAM(2)? expected NAM(1)
@2514aa0 13 INTSXP g0c1 [NAM(2)] (len=1, tl=0) 1
y = 1:10
.Internal(inspect(y)) # NAM(1) as expected but why different to x?
@272f788 13 INTSXP g0c4 [NAM(1)] (len=10, tl=0) 1,2,3,4,5,...
z = data.frame()
.Internal(inspect(z)) # why NAM(2)? expected NAM(1)
@24fc28c 19 VECSXP g0c0 [OBJ,NAM(2),ATT] (len=0, tl=0)
ATTRIB:
@24fc270 02 LISTSXP g0c0 []
TAG: @3f2120 01 SYMSXP g0c0 [MARK,gp=0x4000] "names"
@24fc334 16 STRSXP g0c0 [] (len=0, tl=0)
TAG: @3f2040 01 SYMSXP g0c0 [MARK,gp=0x4000] "row.names"
@24fc318 13 INTSXP g0c0 [] (len=0, tl=0)
TAG: @3f2388 01 SYMSXP g0c0 [MARK,gp=0x4000] "class"
@25be500 16 STRSXP g0c1 [] (len=1, tl=0)
@1d38af0 09 CHARSXP g0c2 [MARK,gp=0x21,ATT] "data.frame"
It's a little difficult to search for the word "named" but I tried and
found this in R-ints :
"Note that optimizing NAMED = 1 is only effective within a primitive
(as the closure wrapper of a .Internal will set NAMED = 2 when the
promise to the argument is evaluated)"
So might it be that just looking at NAMED using .Internal(inspect())
is
setting NAMED=2? But if so, why does y have NAMED==1?
This is tricky business... I'm not quite sure I'll get it right, but
let's
try
When you are assigning a constant, the value you assign is already part
of
the assignment expression, so if you want to modify it, you must
duplicate. So NAMED==2 on z <- 1 is basically to prevent you from
accidentally "changing the value of 1". If it weren't, then you could
get
bitten by code like for(i in 1:2) {z <- 1; if(i==1) z[1] <- 2}.
If you're assigning the result of a computation, then the object only
exists once, so
z <- 0+1 gets NAMED==1.
However, if the computation is done by returning a named value from
within
a function, as in
f <- function(){v <- 1+0; v}
z <- f()
then again NAMED==2. This is because the side effects of the function
_might_ result in something having a hold on the function environment,
e.g. if we had
e <- NULL
f <- function(){e <<-environment(); v <- 1+0; v}
z <- f()
then z[1] <- 5 would change e$v too. As it happens, there aren't any
side
effects in the forme case, but R loses track and assumes the worst.
Thanks a lot, think I follow. That explains x vs y, but why is z
NAMED==2?
The result of data.frame() is an object that exists once (similar to
1:10)
so shouldn't it be NAMED==1 too? Or, R loses track and assumes the
worst
even on its own functions such as data.frame()?
R loses track. I suspect that is really all it can do without actual
reference counting. The function data.frame is more than 150 lines of
code, and if any of those end up invoking user code, possibly via a class
method, you can't tell definitively whether or not the evaluation
environment dies at the return.