I am sorry that this IS an old topic. Yet another task I think the bug is somewhere in hidden in src/main/options.c .. ##-- The following does not work as it should in R (0.50-a1, but I think also earlier) tst <- function(x=pi, dig =3) {.Options$digits <- as.integer(dig); print(x);x} tst() tst(dig = 12) ##-- This should do the same; it works as expected in R & S : tst2 <- function(x=pi, dig =3) { oo <- options(digits=dig); on.exit(oo); print(x);x} tst2() tst2(dig = 12) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-devel-request@stat.math.ethz.ch =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Martin Maechler <maechler@stat.math.ethz.ch> writes:> > I am sorry that this IS an old topic. > Yet another task > I think the bug is somewhere in hidden in src/main/options.c .. > > ##-- The following does not work as it should in R (0.50-a1, but I think > also earlier) > > tst <- function(x=pi, dig =3) {.Options$digits <- as.integer(dig); print(x);x} > tst() > tst(dig = 12) > > > ##-- This should do the same; it works as expected in R & S : > > tst2 <- function(x=pi, dig =3) { > oo <- options(digits=dig); on.exit(oo); print(x);x}^^^^^^^^^^^ on.exit(options(oo))> tst2() > tst2(dig = 12)I'm not sure this is a bug at all, given the scoping rules, etc. However, things are strange. Consider the following:> f<-function(){print(a$b);a$b<-pi;print(a$b)} > f()[1] 2 [1] 2> f<-function(){print(a$b);a<-a;a$b<-pi;print(a$b)} > f()[1] 2 [1] 3.141593 The difference is that in the first case, a is in .GlobalEnv, and not modifiable with "<-" ("<<-" works). Apparently, "$<-" won't automatically create a copy of a in the current environment which is what I had expected. Still, creating .Options explicitly in tst() doesn't work, which fact is probably due to the digits argument in print.default defaulting to NULL, and print.default has no reason to look on the frame stack for .Options. However, changing the print.default definition to print.default<-function (x, digits = eval(expression(.Options$digits), sys.frame(sys.parent())), quote = TRUE, na.print = NULL, print.gap = NULL) { .Internal(print.default(x, digits, quote, na.print, print.gap)) } *and* tst<-function (x = pi, dig = 3) { .Options <- .Options .Options$digits <- as.integer(dig) print(x) x } does seem to do what you wanted... -- O__ ---- Peter Dalgaard Blegdamsvej 3 c/ /'_ --- Dept. of Biostatistics 2200 Cph. N (*) \(*) -- University of Copenhagen Denmark Ph: (+45) 35327918 ~~~~~~~~~~ - (p.dalgaard@biostat.ku.dk) FAX: (+45) 35327907 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-devel-request@stat.math.ethz.ch =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Martin wrote:> I am sorry that this IS an old topic. > Yet another task > I think the bug is somewhere in hidden in src/main/options.c .. > > ##-- The following does not work as it should in R (0.50-a1, but I think > also earlier) > > tst <- function(x=pi, dig =3) {.Options$digits <- as.integer(dig); print(x);x} > tst() > tst(dig = 12) > > > ##-- This should do the same; it works as expected in R & S : > > tst2 <- function(x=pi, dig =3) { > oo <- options(digits=dig); on.exit(oo); print(x);x} > tst2() > tst2(dig = 12)Well it isn't really clear what Splus does to get tst to work. It appears that they use some form of dynamic scope for Options. Clearly, the assignment, .Options$digits<- xxxx creates a local copy of .Options and changes the value of that. The only way that print can find this local copy is if it looks up the stack of calling functions to find it (or perhaps Splus squirrels it away somewhere that print looks but then <- starts to behave in a very peculiar manner). This sort of behaviour is bad for two reasons 1) We really want people to use lexical scope and any examples where you have dynamic scope simply confuse things 2) It is quite inefficient for print (and anything else that uses Options) to have to look up the stack of calling functions. Since the method Martin so capably demonstrated with tst2 does work (except I think he meant on.exit(options(oo)) rather than on.exit(oo)) I think we should stick with that. In that case the global value of options(digits) is changed for the duration of the function evaluation of tst2. robert =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-devel-request@stat.math.ethz.ch =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
> From pd@kubism.ku.dk Wed Aug 13 23:11 NZS 1997 > To: Robert Gentleman <rgentlem@stat.auckland.ac.nz> > Cc: R-devel@stat.math.ethz.ch > Subject: Re: R-alpha: .Options$digits do not (always) work. > From: Peter Dalgaard BSA <p.dalgaard@kubism.ku.dk> > Date: 13 Aug 1997 13:13:35 +0200 > > Robert Gentleman <rgentlem@stat.auckland.ac.nz> writes: > > > Well it isn't really clear what Splus does to get tst to work. It appears > > that they use some form of dynamic scope for Options. Clearly, the > > assignment, > > .Options$digits<- xxxx > > creates a local copy of .Options and changes the value of that. The only > > way that print can find this local copy is if it looks up the stack of > > calling functions to find it (or perhaps Splus squirrels it away somewhere > > Couldn't one have the digits argument of print default to > .Options$digits (or is that eval(.Options$digits, > sys.frame(sys.parent)) ??)Ah, but how far up do you look? That's fine if print is called from the function that sets .Options but what if it is called from a function that is called from the function that is....called from the function that set .Options. Looking back up all of these is dynamic scope. It is pretty inefficient for print to have to look in all these places for a .Options before it can do its thing. Alternatively you could say that print either gets .Options from the parent or from top level and so it looks in sys.frame(sys.parent) but then someone will want to do it from the grandparent and not understand why it doesn't work. I think it would be nice if Martin's example ended up in the FAQ (or a programming examples repository) with an explanation that the global .Options is checked; local copies aren't and that if you want to affect the global value you can do it in the manner shown in the example. I think this is a big change from what S does so it should be well signposted. robert =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-devel-request@stat.math.ethz.ch =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-