[Rd] Changing graphic titles when using bquote and resizing the graphic window
Dear list, I found a strange behavior of the graphic display when using bquote to set a title to a plot. The problem arise when you manually resize the graphic window using the mouse. It happens on both quartz and x11 devices. Here's a reproducible example: par(mfrow = c(1,3)) for (i in 1:3){ title <- as.expression(bquote(gamma[.(i)])) plot(1:10, main = title) } Once you ran the code, the figure displays as expected --- each title is $\gamma_i$, $i=1, 2, 3$. Now if you resize manually the graphic window using the mouse all the titles will be set to $\gamma_3$. In case this is useful, here's the ouput of sessionInfo(). > sessionInfo() R version 2.14.0 (2011-10-31) Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit) locale: [1] C attached base packages: [1] stats graphics grDevices utils datasets methods base Best, Mathieu - I3M, UMR CNRS 5149 Universite Montpellier II, 4 place Eugene Bataillon 34095 Montpellier cedex 5 France http://www.math.univ-montp2.fr/~ribatet Tel: + 33 (0)4 67 14 41 98 __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
[Rd] Confused about NAMED
Hi, I expected NAMED to be 1 in all these three cases. It is for one of them, but not the other two? > R --vanilla 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? Thanks! Matthew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
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 --vanilla > 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! > Matthew > > __ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel -- Peter Dalgaard, Professor Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Email: pd@cbs.dk Priv: pda...@gmail.com __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
> > 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 --vanilla >> 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()? >> >> Thanks! >> Matthew >> >> __ >> R-devel@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > > -- > Peter Dalgaard, Professor > Center for Statistics, Copenhagen Business School > Solbjerg Plads 3, 2000 Frederiksberg, Denmark > Phone: (+45)38153501 > Email: pd@cbs.dk Priv: pda...@gmail.com > > __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Changing graphic titles when using bquote and resizing the graphic window
(Why is this an R-devel topic?) When you resize a plot (and sometimes when the graph is repainted), the display list is replay-ed. So if you force delayed evaluation, you get evaluation when the list is replay-ed. So the 'strange' thing is that you think delaying evaluation is a good idea. Use substitute, as the R help pages advise. E.g. par(mfrow = c(1,3)) for (i in 1:3){ title <- substitute(gamma[j], list(j=i)) plot(1:10, main = title) } On 24/11/2011 08:54, Mathieu Ribatet wrote: Dear list, I found a strange behavior of the graphic display when using bquote to set a title to a plot. The problem arise when you manually resize the graphic window using the mouse. It happens on both quartz and x11 devices. Here's a reproducible example: par(mfrow = c(1,3)) for (i in 1:3){ title<- as.expression(bquote(gamma[.(i)])) plot(1:10, main = title) } Once you ran the code, the figure displays as expected --- each title is $\gamma_i$, $i=1, 2, 3$. Now if you resize manually the graphic window using the mouse all the titles will be set to $\gamma_3$. In case this is useful, here's the ouput of sessionInfo(). sessionInfo() R version 2.14.0 (2011-10-31) Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit) locale: [1] C attached base packages: [1] stats graphics grDevices utils datasets methods base Best, Mathieu - I3M, UMR CNRS 5149 Universite Montpellier II, 4 place Eugene Bataillon 34095 Montpellier cedex 5 France http://www.math.univ-montp2.fr/~ribatet Tel: + 33 (0)4 67 14 41 98 __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel -- Brian D. Ripley, rip...@stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UKFax: +44 1865 272595 __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
On 11-11-24 6:34 AM, 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 --vanilla 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 has several types of functions -- see the R Internals manual for details. data.frame() is a plain R function, so it is treated no differently than any user-written function. On the other hand, the internal function that implements the : operator is a "primitive", so it has complete control over its return value, and it can set NAMED in the most efficient way. So you might think that returning a value as an evaluation of a primitive adds efficiency, e.g. in Peter's example f<- function(){v<- 1+0; v + 0} will return NAMED == 1. But that's because internally it had to make a copy of v before adding 0 to it, so you've probably really made it less efficient: the original version might never modify the result, so it might never make a copy. Duncan Murdoch __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
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 --vanilla >>> 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. -- Peter Dalgaard, Professor Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Email: pd@cbs.dk Priv: pda...@gmail.com __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
> > 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 --vanilla 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. Ohhh, think I see now. After Duncan's reply I was going to ask if it was possible to change data.frame() to be primitive so it could set NAMED=1. But it seems primitive functions can't use R code so data.frame() would need to be ported to C. Ok! - not quick or easy, and not without consideable risk. And, data.frame() can invoke user code inside it anyway then. Since list() is primitive I tried to construct a data.frame starting with list() [since structure() isn't primitive], but then merely adding an attribute seems to set NAMED==2 too ? > DF = list(a=1:3,b=4:6) > .Internal(inspect(DF)) # so far so good: NAM(1) @25149e0 19 VECSXP g0c1 [NAM(1),ATT] (len=2, tl=0) @263ea50 13 INTSXP g0c2 [] (len=3, tl=0) 1,2,3 @263eaa0 13 INTSXP g0c2 [] (len=3, tl=0) 4,5,6 ATTRIB: @2457984 02 LISTSXP g0c0 [] TAG: @3f2120 01 SYMSXP g0c0 [MARK,gp=0x4000] "names" @25149c0 16 STRSXP g0c1 [] (len=2, tl=0) @1e987d8 09 CHARSXP g0c1 [MARK,gp=0x21] "a" @1e56948 09 CHARSXP g0c1 [MARK,gp=0x21] "b" > > attr(DF,"foo") <- "bar"# just adding an attribute sets NAM(2) ? > .Internal(inspect(DF)) @25149e0 19 VECSXP g0c1 [NAM(2),ATT] (len=2, tl=0) @263ea50 13 INTSXP g0c2 [] (len=3, tl=0) 1,2,3 @263eaa0 13 INTSXP g0c2 [] (len=3, tl=0) 4,5,6 ATTRIB: @2457984 02 LISTSXP g0c0 [] TAG: @3f2120 01 SYMSXP g0c0 [MARK,gp=0x4000] "names" @25149c0 16 STRSXP g0c1 [] (len=2, tl=0) @1e987d8 09 CHARSXP g0c1 [MARK,gp=0x21] "a" @1e56948 09 CHARSXP g0c1 [MARK,gp=0x21] "b" TAG: @245732c 01
Re: [Rd] capture.output(eval(..., envir)) not evaluate in the expected(?) environment
On Nov 23, 2011, at 11:06 PM, Henrik Bengtsson wrote: > Thanks for the quick answer. I didn't know about force() function. > It doesn't matter how you force the argument, anything - e.g. if(is.environment(envir)) capture.output(...) would do - I used force() just to make the point that it is what is causing it. A more simple example illustrating what happens here: > f = function(e=parent.frame()) local(print(e)) > f() > f = function(e=parent.frame()) { force(e); local(print(e)) } > f() > f = function(e=parent.frame()) if (is.environment(e)) local(print(e)) > f() Cheers, Simon > Cheers, > > Henrik > > On Wed, Nov 23, 2011 at 6:56 PM, Simon Urbanek > wrote: >> IMHO this has nothing to do with capture.output() per se - it's simply lazy >> evaluation that gets you. Add force(envir) before capture.output and it >> works as you expected - the parent.frame() will be different inside >> capture.output than outside. >> >> Cheers, >> Simon >> >> >> On Nov 23, 2011, at 9:36 PM, Henrik Bengtsson wrote: >> >>> I've noticed the following oddity where capture.output() prevents >>> eval() from evaluating an expression in the specified environment. >>> I'm not sure if it is an undocumented feature or a bug. It caused me >>> many hours of troubleshooting. By posting it here, it might save >>> someone else from doing the same exercise. >>> >>> Start by defining foo() which evaluates an expression locally in a >>> given environment and catches the output via capture.output(): >>> >>> foo <- function(..., envir=parent.frame()) { >>> capture.output({ >>>eval(substitute({x <- 1}), envir=envir) >>> }) >>> } # foo() >>> >>> Then call: >>> suppressWarnings(rm(x)); foo(envir=globalenv()); print(x); >>> character(0) >>> [1] 1 >>> >>> This works as expected. However, if argument 'envir' is not specified >>> explicitly, you get: >>> suppressWarnings(rm(x)); foo(); str(x); >>> character(0) >>> Error in str(x) : object 'x' not found >>> >>> which shows that the internal expression of foo() is *not* evaluated >>> in the parent.frame(), i.e. the caller of foo(), which here should be >>> globalenv(). It appears that capture.output() prevents this, because >>> by dropping the latter: >>> >>> foo <- function(..., envir=parent.frame()) { >>> eval(substitute({x <- 1}), envir=envir) >>> } # foo() >>> >>> it works: >>> suppressWarnings(rm(x)); foo(); str(x); >>> [1] 1 >>> >>> The workaround when still using capture.output() is to force an >>> explicit evaluation of argument 'envir' inside of foo() before: >>> >>> foo <- function(..., envir=parent.frame()) { >>> stopifnot(is.environment(envir)) # Workaround >>> capture.output({ >>>eval(substitute({x <- 1}), envir=envir) >>> }) >>> } # foo() >>> >>> which gives: suppressWarnings(rm(x)); foo(); str(x); >>> character(0) >>> num 1 >>> >>> This occurs with R v2.14.0 patched and R devel: >>> sessionInfo() >>> R version 2.14.0 Patched (2011-11-20 r57720) >>> Platform: x86_64-pc-mingw32/x64 (64-bit) >>> >>> locale: >>> [1] LC_COLLATE=English_United States.1252 >>> [2] LC_CTYPE=English_United States.1252 >>> [3] LC_MONETARY=English_United States.1252 >>> [4] LC_NUMERIC=C >>> [5] LC_TIME=English_United States.1252 >>> >>> attached base packages: >>> [1] stats graphics grDevices utils datasets methods base >>> sessionInfo() >>> R Under development (unstable) (2011-11-20 r57720) >>> Platform: x86_64-pc-mingw32/x64 (64-bit) >>> >>> locale: >>> [1] LC_COLLATE=English_United States.1252 >>> [2] LC_CTYPE=English_United States.1252 >>> [3] LC_MONETARY=English_United States.1252 >>> [4] LC_NUMERIC=C >>> [5] LC_TIME=English_United States.1252 >>> >>> attached base packages: >>> [1] stats graphics grDevices utils datasets methods base >>> >>> /Henrik >>> >>> __ >>> R-devel@r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel >>> >>> >> >> > > __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
On Nov 24, 2011, at 14:05 , Matthew Dowle wrote: > Since list() is primitive I tried to construct a data.frame starting with > list() [since structure() isn't primitive], but then merely adding an > attribute seems to set NAMED==2 too ? Yes. As soon as there is the slightest risk of having (had) two references to the same object NAMED==2 and it is never reduced. While your mind is boggling, I might boggle it a bit more: > z <- 1:10 > .Internal(inspect(z)) @116e11788 13 INTSXP g0c4 [NAM(1)] (len=10, tl=0) 1,2,3,4,5,... > m <- mean(z) > .Internal(inspect(z)) @116e11788 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,... This happens because while mean() is running, there is a second reference to z, namely mean's argument x. (With languages like R, you have no insurance that there will be no changes to the global environment while a function call is being evaluated, so bugs can bite in both places -- z or x.) There are many of these cases where you might pragmatically want to override the default NAMED logic, but you'd be stepping into treacherous waters. Luke has probably been giving these matters quite some thought in connection with his compiler project. -- Peter Dalgaard, Professor Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Email: pd@cbs.dk Priv: pda...@gmail.com __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
> > On Nov 24, 2011, at 14:05 , Matthew Dowle wrote: > >> Since list() is primitive I tried to construct a data.frame starting >> with >> list() [since structure() isn't primitive], but then merely adding an >> attribute seems to set NAMED==2 too ? > > Yes. As soon as there is the slightest risk of having (had) two references > to the same object NAMED==2 and it is never reduced. While your mind is > boggling, I might boggle it a bit more: > >> z <- 1:10 >> .Internal(inspect(z)) > @116e11788 13 INTSXP g0c4 [NAM(1)] (len=10, tl=0) 1,2,3,4,5,... >> m <- mean(z) >> .Internal(inspect(z)) > @116e11788 13 INTSXP g0c4 [NAM(2)] (len=10, tl=0) 1,2,3,4,5,... > > This happens because while mean() is running, there is a second reference > to z, namely mean's argument x. (With languages like R, you have no > insurance that there will be no changes to the global environment while a > function call is being evaluated, so bugs can bite in both places -- z or > x.) > > There are many of these cases where you might pragmatically want to > override the default NAMED logic, but you'd be stepping into treacherous > waters. Luke has probably been giving these matters quite some thought in > connection with his compiler project. Ok, very interesting. Think I'm there. Thanks for all the info. Matthew __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Confused about NAMED
On Nov 24, 2011, at 8:05 AM, Matthew Dowle wrote: >> >> 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 --vanilla > 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. > > Ohhh, think I see now. After Duncan's reply I was going to ask if it was > possible to change data.frame() to be primitive so it could set NAMED=1. > But it seems primitive functions can't use R code so data.frame() would > need to be ported to C. Ok! - not quick or easy, and not without > consideable risk. And, data.frame() can invoke user code inside it anyway > then. > > Since list() is primitive I tried to construct a data.frame starting with > list() [since structure() isn't primitive], but then merely adding an > attribute seems to set NAMED==2 too ? > Yes, because attr(x,y) <- z is the same as `*tmp*` <- x x <- `attr<-`(`*tmp*`, y, z) rm(`*tmp*`) so there are two references to the data frame: one in DF and one in `*tmp*`. It is the first line that causes the NAMED bump. And, yes, it's real: > `f<-`=function(x,value) { print(ls(parent.frame())); x<-value } > x=1 > f(x)=1 [1] "*tmp*" "f<-" "x" You could skip that by using the function directly (I don't think it's recommended, though): > .Internal(inspect(l <- list(a=1))) @1028c82f8 19 VECSXP g0c1 [NAM(1),ATT] (len=1, tl=0) @1028c8268 14 REALSXP g0c1 [] (len=1, tl=0) 1 ATTRIB: @100b6e748 02 LISTSXP g0c0 [] TAG: @100843878 01 SYMSXP g0c0 [MARK,gp=0x4000] "names" @1028c82c8 16 STRSXP g0c1 [] (len=1, tl=0) @1009cd388 09 CHARSXP g0c1 [MARK,gp=0x21]
Re: [Rd] Confused about NAMED
The details of complex assignment expressions are fairly intricate. I wrote up some notes ont his a couple of months back and have meant to get them into the internals manual but have not gotten around to it yet. I'll see if I can get to it in the next week or two and will send a note to this thread wehen I do. In terms of the issues discussed so far Calling a foo<- function directly is not a good idea unless you really undestand what is going on in the assignment mechanism in general and in the particular foo<- function. It is definitely not something to be done in routine programming unless you like unpleasant surprises. attr<- could probably be modified to avine the NAMED increment in this example, but I'd want to think that through fairly carefully before making such a change. (Most foo<- functions that are primitives are written to that they avoid a NAMED increment when used in an assignment expression, but a few are not -- I believe these are almost all, maybe even all, oversights, but again I wouldn't want to make any changes without ceareful review.) Best, luke On Thu, 24 Nov 2011, Simon Urbanek wrote: On Nov 24, 2011, at 8:05 AM, Matthew Dowle wrote: 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 --vanilla 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. Ohhh, think I see now. After Duncan's reply I was going to ask if it was possible to change data.frame() to be primitive so it could set NAMED=1. But it seems primitive functions can't use R code so data.frame() would need to be ported to C. Ok! - not quick or easy, and not without consideable risk. And, data.frame() can invoke user code inside it anyway then. Since list() is primitive I tried to construct a data.frame starting with list() [since structure() isn't primitive], but then merely adding an attribute seems to set NAMED==2 too ? Yes, because attr(x,y) <- z is the same as `*tmp*` <- x x <- `attr<-`(`*tmp*`, y, z) rm(`*tmp*`) so there are two references to the data
Re: [Rd] Confused about NAMED
> > On Nov 24, 2011, at 8:05 AM, Matthew Dowle wrote: > >>> >>> 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 --vanilla >> 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. >> >> Ohhh, think I see now. After Duncan's reply I was going to ask if it was >> possible to change data.frame() to be primitive so it could set NAMED=1. >> But it seems primitive functions can't use R code so data.frame() would >> need to be ported to C. Ok! - not quick or easy, and not without >> consideable risk. And, data.frame() can invoke user code inside it >> anyway >> then. >> >> Since list() is primitive I tried to construct a data.frame starting >> with >> list() [since structure() isn't primitive], but then merely adding an >> attribute seems to set NAMED==2 too ? >> > > Yes, because attr(x,y) <- z is the same as > > `*tmp*` <- x > x <- `attr<-`(`*tmp*`, y, z) > rm(`*tmp*`) > > so there are two references to the data frame: one in DF and one in > `*tmp*`. It is the first line that causes the NAMED bump. And, yes, it's > real: > >> `f<-`=function(x,value) { print(ls(parent.frame())); x<-value } >> x=1 >> f(x)=1 > [1] "*tmp*" "f<-" "x" > > You could skip that by using the function directly (I don't think it's > recommended, though): > >> .Internal(inspect(l <- list(a=1))) > @1028c82f8 19 VECSXP g0c1 [NAM(1),ATT] (len=1, tl=0) > @1028c8268 14 REALSXP g0c1 [] (len=1, tl=0) 1 > ATTRIB: > @100b6e748 02 LISTSXP
Re: [Rd] Confused about NAMED
On Thu, 24 Nov 2011, Simon Urbanek wrote: On Nov 24, 2011, at 8:05 AM, Matthew Dowle wrote: 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 --vanilla 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. Ohhh, think I see now. After Duncan's reply I was going to ask if it was possible to change data.frame() to be primitive so it could set NAMED=1. But it seems primitive functions can't use R code so data.frame() would need to be ported to C. Ok! - not quick or easy, and not without consideable risk. And, data.frame() can invoke user code inside it anyway then. Maybe some review of the 'R Internals' manual about what a primitive function is would be desirable. Converting such a function to C would ossify it, which is the major reason it has not been done (it has been contemplated). Since list() is primitive I tried to construct a data.frame starting with list() [since structure() isn't primitive], but then merely adding an attribute seems to set NAMED==2 too ? Yes, because attr(x,y) <- z is the same as `*tmp*` <- x x <- `attr<-`(`*tmp*`, y, z) rm(`*tmp*`) Only if it were an interpreted function. so there are two references to the data frame: one in DF and one in `*tmp*`. It is the first line that causes the NAMED bump. And, yes, it's real: `f<-`=function(x,value) { print(ls(parent.frame())); x<-value } x=1 f(x)=1 [1] "*tmp*" "f<-" "x" You have just explained why interpreted replacement functions set NAMED=2, but this does not apply to primitives. To help convince you, consider d <- 1:2 attributes(d) <- list(x=13) d [1] 1 2 attr(,"x") [1] 13 .Internal(inspect(d)) @11be748 13 INTSXP g0c1 [NAM(1),ATT] (len=2, tl=0) 1,2 ATTRIB: @1552054 02 LISTSXP g0c0 [] TAG: @102b1c0 01 SYMSXP g0c0 [MARK,NAM(2)] "x" @11be768 14 REALSXP g0c1 [] (len=1, tl=0) 13 Now, as to why attr<- (which is primitive) does what it does you will need to read (and understand) the code. You could skip that by using the function directly (I don't think it's recomm
Re: [Rd] Confused about NAMED
On Nov 24, 2011, at 1:48 PM, Prof Brian Ripley wrote: > On Thu, 24 Nov 2011, Simon Urbanek wrote: > >> >> On Nov 24, 2011, at 8:05 AM, Matthew Dowle wrote: >> 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 --vanilla >>> 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. >>> >>> Ohhh, think I see now. After Duncan's reply I was going to ask if it was >>> possible to change data.frame() to be primitive so it could set NAMED=1. >>> But it seems primitive functions can't use R code so data.frame() would >>> need to be ported to C. Ok! - not quick or easy, and not without >>> consideable risk. And, data.frame() can invoke user code inside it anyway >>> then. > > Maybe some review of the 'R Internals' manual about what a primitive function > is would be desirable. Converting such a function to C would ossify it, > which is the major reason it has not been done (it has been contemplated). > >>> Since list() is primitive I tried to construct a data.frame starting with >>> list() [since structure() isn't primitive], but then merely adding an >>> attribute seems to set NAMED==2 too ? >>> >> >> Yes, because attr(x,y) <- z is the same as >> >> `*tmp*` <- x >> x <- `attr<-`(`*tmp*`, y, z) >> rm(`*tmp*`) > > Only if it were an interpreted function. > >> so there are two references to the data frame: one in DF and o
[Rd] How to deal with package conflicts
In my genridge package, I define a function ridge() for ridge regression, creating objects of class 'ridge' that I intend to enhance. In a documentation example, I want to use some functions from the car package. However, that package requires survival, which also includes a ridge() function, for coxph models. So, once I require(car) my ridge() function is masked, which means I have to use the awkward form below in my .Rd files. ridgemod <- genridge::ridge(...) I tried to detach survival, but that doesn't work: > detach("package:survival") Error: package ‘survival’ is required by ‘car’ so will not be detached I don't see any solution to this, other than (a) renaming my ridge() to something else -- don't want to do this (b) use \dontrun{} for the examples that use car Or, is there some other way? -- Michael Friendly Email: friendly AT yorku DOT ca Professor, Psychology Dept. York University Voice: 416 736-5115 x66249 Fax: 416 736-5814 4700 Keele StreetWeb: http://www.datavis.ca Toronto, ONT M3J 1P3 CANADA __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] How to deal with package conflicts
On 11-11-24 4:44 PM, Michael Friendly wrote: In my genridge package, I define a function ridge() for ridge regression, creating objects of class 'ridge' that I intend to enhance. In a documentation example, I want to use some functions from the car package. However, that package requires survival, which also includes a ridge() function, for coxph models. So, once I require(car) my ridge() function is masked, which means I have to use the awkward form below in my .Rd files. ridgemod<- genridge::ridge(...) I tried to detach survival, but that doesn't work: > detach("package:survival") Error: package ‘survival’ is required by ‘car’ so will not be detached I don't see any solution to this, other than (a) renaming my ridge() to something else -- don't want to do this (b) use \dontrun{} for the examples that use car Or, is there some other way? Not really. I'd say the renaming is the preferred way to go, but you might also be able to convince Terry Therneau (survival author) to make ridge() a generic, so your method is called for your objects, and his is called for others. Duncan Murdoch __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel