Re: [Rd] withAutoprint({ .... }) ?
> William Dunlap > on Fri, 2 Sep 2016 08:33:47 -0700 writes: > Re withAutoprint(), Splus's source() function could take a expression > (literal or not) in place of a file name or text so it could support > withAutoprint-like functionality in its GUI. E.g., >> source(auto.print=TRUE, exprs.literal= { x <- 3:7 ; sum(x) ; y <- log(x) > ; x - 100}, prompt="--> ") --> x <- 3:7 --> sum(x) > [1] 25 --> y <- log(x) --> x - 100 > [1] -97 -96 -95 -94 -93 > or >> expr <- quote({ x <- 3:7 ; sum(x) ; y <- log(x) ; x - 100}) >> source(auto.print=TRUE, exprs = expr, prompt="--> ") --> x <- 3:7 --> sum(x) > [1] 25 --> y <- log(x) --> x - 100 > [1] -97 -96 -95 -94 -93 > It was easy to implement, since exprs's default value is parse(file) or > parse(text=text), which source is calculating anyway. > Bill Dunlap > TIBCO Software > wdunlap tibco.com Thank you, Bill (and the other correspondents); that's indeed a very good suggestion : I've come to the conclusion that Duncan and Bill are right: One should do this in R (not C) and as Bill hinted, one should use source(). I first tried to do it separately, just "like source()", but a considerable part of the source of source() {:-)} is about using src attributes instead of deparse() when the former are present, and it does make sense to generalize withAutoprint() to have the same feature, so after all, have it call source(). I've spent a few hours now trying things and variants, also found I needed to enhance source() very slightly also in a few other details, and now (in my uncommitted version of R-devel), withAutoprint({ x <- 1:12; x-1; (y <- (x-5)^2); z <- y; z - 10 }) produces > withAutoprint({ x <- 1:12; x-1; (y <- (x-5)^2); z <- y; z - 10 }) > x <- 1:12 > x - 1 [1] 0 1 2 3 4 5 6 7 8 9 10 11 > (y <- (x - 5)^2) [1] 16 9 4 1 0 1 4 9 16 25 36 49 > z <- y > z - 10 [1] 6 -1 -6 -9 -10 -9 -6 -1 6 15 26 39 > and is equivalent to withAutoprint(expression(x <- 1:12, x-1, (y <- (x-5)^2), z <- y, z - 10 )) I don't see any way around the "mis-feature" that all "input" expressions are in the end shown twice in the "output" (the first time by showing the withAutoprint(...) call itself). The function *name* is "not bad" but also a bit longish; maybe there are better ideas? (not longer, no "_" - I know this is a matter of taste only) Martin > On Fri, Sep 2, 2016 at 4:56 AM, Martin Maechler > wrote: >> On R-help, with subject >> '[R] source() does not include added code' >> >> > Joshua Ulrich >> > on Wed, 31 Aug 2016 10:35:01 -0500 writes: >> >> > I have quantstrat installed and it works fine for me. If you're >> > asking why the output of t(tradeStats('macross')) isn't being >> printed, >> > that's because of what's described in the first paragraph in the >> > *Details* section of help("source"): >> >> > Note that running code via ‘source’ differs in a few respects from >> > entering it at the R command line. Since expressions are not >> > executed at the top level, auto-printing is not done. So you will >> > need to include explicit ‘print’ calls for things you want to be >> > printed (and remember that this includes plotting by ‘lattice’, >> > FAQ Q7.22). >> >> >> >> > So you need: >> >> > print(t(tradeStats('macross'))) >> >> > if you want the output printed to the console. >> >> indeed, and "of course"" ;-) >> >> As my subject indicates, this is another case, where it would be >> very convenient to have a function >> >> withAutoprint() >> >> so the OP could have (hopefully) have used >> withAutoprint(source(..)) >> though that would have been equivalent to the already nicely existing >> >> source(.., print.eval = TRUE) >> >> which works via the withVisible(.) utility that returns for each >> 'expression' if it would auto print or not, and then does print (or >> not) accordingly. >> >> My own use cases for such a withAutoprint({...}) >> are demos and examples, sometimes even package tests which I want to print: >> >> Assume I have a nice demo / example on a help page/ ... >> >> foo(..) >> (z <- bar(..)) >> summary(z) >> >> >> where I carefully do print parts (and don't others), >> and suddenly I find I want to run that part of the demo / >> example / test only in some circumstances, e.g., only when >> interactive, but not in BATCH, or only if it is me, the package maintainer, >> >> if( identical(Sys.getenv("USER"), "maechler") ) { >> foo(..) >> (z <- bar(..)) >> summary(z) >> >> } >> >> Now all the auto-printing is gone, and >> >> 1) I have to find
Re: [Rd] Undocumented 'use.names' argument to c()
> Karl Millar via R-devel > on Fri, 23 Sep 2016 11:12:49 -0700 writes: > I'd expect that a lot of the performance overhead could be eliminated > by simply improving the underlying code. IMHO, we should ignore it in > deciding the API that we want here. I agree partially. Even if the underlying code can be made faster, the 'use.names = FALSE' version will still be faster than the default, notably in some "long" cases. More further down. > On Fri, Sep 23, 2016 at 10:54 AM, Henrik Bengtsson > wrote: >> I'd vote for it to stay. It could of course suprise someone who'd >> expect c(list(a=1), b=2, use.names = FALSE) to generate list(a=1, b=2, >> use.names=FALSE). On the upside, is the performance gain from using >> use.names=FALSE. Below benchmarks show that the combining of the >> names attributes themselves takes ~20-25 times longer than the >> combining of the integers themselves. Also, at no surprise, >> use.names=FALSE avoids some memory allocations. >> >>> options(digits = 2) >>> >>> a <- b <- c <- d <- 1:1e4 >>> names(c) <- c >>> names(d) <- d >>> >>> stats <- microbenchmark::microbenchmark( >> + c(a, b, use.names=FALSE), >> + c(c, d, use.names=FALSE), >> + c(a, d, use.names=FALSE), >> + c(a, b, use.names=TRUE), >> + c(a, d, use.names=TRUE), >> + c(c, d, use.names=TRUE), >> + unit = "ms" >> + ) >>> >>> stats >> Unit: milliseconds >> expr minlq mean medianuq max neval >> c(a, b, use.names = FALSE) 0.031 0.032 0.049 0.034 0.036 1.474 100 >> c(c, d, use.names = FALSE) 0.031 0.031 0.035 0.034 0.035 0.064 100 >> c(a, d, use.names = FALSE) 0.031 0.031 0.049 0.034 0.035 1.452 100 >> c(a, b, use.names = TRUE) 0.031 0.031 0.055 0.034 0.036 2.094 100 >> c(a, d, use.names = TRUE) 0.510 0.526 0.588 0.549 0.617 1.998 100 >> c(c, d, use.names = TRUE) 0.780 0.815 0.886 0.841 0.944 1.430 100 >> >>> profmem::profmem(c(c, d, use.names=FALSE)) >> Rprofmem memory profiling of: >> c(c, d, use.names = FALSE) >> >> Memory allocations: >> bytes calls >> 1 80040 >> total 80040 >> >>> profmem::profmem(c(c, d, use.names=TRUE)) >> Rprofmem memory profiling of: >> c(c, d, use.names = TRUE) >> >> Memory allocations: >> bytes calls >> 1 80040 >> 2 160040 >> total 240080 >> >> /Henrik >> >> On Fri, Sep 23, 2016 at 10:25 AM, William Dunlap via R-devel >> wrote: >>> In Splus c() and unlist() called the same C code, but with a different >>> 'sys_index' code (the last argument to .Internal) and c() did not consider >>> an argument named 'use.names' special. Thank you, Bill, very much, for making the historical context clear, and giving us the facts, there. OTOH, it is also true in R, that c() and unlist() share code .. quite a bit less though .. but more importantly, the very original C code of Ross Ihaka (and possibly Robert Gentleman) had explicitly considered both extra arguments 'recursive' and 'use.names', and not just the first. The fact that c() has always been a .Primitive function and that these have no formals() had contributed to what I think to be a documentation glitch early on, and when, quite a bit later, we've added a fake argument list for printing, the then current documentation was used. This was the reason for declaring it a documentation "hole" rather than something we do not want. (read on) c >>> function(..., recursive = F) >>> .Internal(c(..., recursive = recursive), "S_unlist", TRUE, 1) unlist >>> function(data, recursive = T, use.names = T) >>> .Internal(unlist(data, recursive = recursive, use.names = use.names), >>> "S_unlist", TRUE, 2) c(A=1,B=2,use.names=FALSE) >>> A B use.names >>> 1 2 0 >>> >>> The C code used sys_index==2 to mean 'the last argument is the 'use.names' >>> argument, if sys_index==1 only the recursive argument was considered >>> special. >>> >>> Sys.funs.c: >>> 405 S_unlist(vector *ent, vector *arglist, s_evaluator *S_evaluator) >>> 406 { >>> 407 int which = sys_index; boolean named, recursive, names; >>> ... >>> 419 args = arglist->value.tree; n = arglist->length; >>> ... >>> 424 names = which==2 ? logical_value(args[--n], ent, S_evaluator) >>> : (which == 1); >>> >>> Thus there is no historical reason for giving c() the use.names argument. >>> >>> >>> Bill Dunlap >>> TIBCO Software >>> wdunlap tibco.com >>> >>> On Fri, Sep 23, 2016 at 9:37 AM, Suharto Anggono Suharto Anggono via >>> R-devel wrote: >>> In S-PLUS 3.4 help on 'c' (http://www.uni-muenster.de/ ZIV.BennoSueselbeck/s-html/helpfiles/c.html), there is n
Re: [Rd] withAutoprint({ .... }) ?
Martin, did you post your code for withAutoprint() anywhere? Building withAutoprint() on top of source() definitely makes sense, unless, as Bill says, source() itself could provide the same feature. To differentiate between withAutoprint({ x <- 1 }) and withAutoprint(expr) where is an expression / language object, one could have an optional argument `substitute=TRUE`, e.g. withAutoprint <- function(expr, substitute = TRUE, ...) { if (substitute) expr <- substitute(expr) [...] } Just some thoughts /Henrik On Sat, Sep 24, 2016 at 6:37 AM, Martin Maechler wrote: >> William Dunlap >> on Fri, 2 Sep 2016 08:33:47 -0700 writes: > > > Re withAutoprint(), Splus's source() function could take a expression > > (literal or not) in place of a file name or text so it could support > > withAutoprint-like functionality in its GUI. E.g., > > >> source(auto.print=TRUE, exprs.literal= { x <- 3:7 ; sum(x) ; y <- > log(x) > > ; x - 100}, prompt="--> ") > --> x <- 3:7 > --> sum(x) > > [1] 25 > --> y <- log(x) > --> x - 100 > > [1] -97 -96 -95 -94 -93 > > > or > > >> expr <- quote({ x <- 3:7 ; sum(x) ; y <- log(x) ; x - 100}) > >> source(auto.print=TRUE, exprs = expr, prompt="--> ") > --> x <- 3:7 > --> sum(x) > > [1] 25 > --> y <- log(x) > --> x - 100 > > [1] -97 -96 -95 -94 -93 > > > It was easy to implement, since exprs's default value is parse(file) or > > parse(text=text), which source is calculating anyway. > > > > Bill Dunlap > > TIBCO Software > > wdunlap tibco.com > > Thank you, Bill (and the other correspondents); that's indeed a > very good suggestion : > > I've come to the conclusion that Duncan and Bill are right: One > should do this in R (not C) and as Bill hinted, one should use > source(). I first tried to do it separately, just "like source()", > but a considerable part of the source of source() {:-)} is > about using src attributes instead of deparse() when the former > are present, and it does make sense to generalize > withAutoprint() to have the same feature, so after all, have it > call source(). > > I've spent a few hours now trying things and variants, also > found I needed to enhance source() very slightly also in a few > other details, and now (in my uncommitted version of R-devel), > > withAutoprint({ x <- 1:12; x-1; (y <- (x-5)^2); z <- y; z - 10 }) > > produces > >> withAutoprint({ x <- 1:12; x-1; (y <- (x-5)^2); z <- y; z - 10 }) >> x <- 1:12 >> x - 1 > [1] 0 1 2 3 4 5 6 7 8 9 10 11 >> (y <- (x - 5)^2) > [1] 16 9 4 1 0 1 4 9 16 25 36 49 >> z <- y >> z - 10 > [1] 6 -1 -6 -9 -10 -9 -6 -1 6 15 26 39 >> > > and is equivalent to > >withAutoprint(expression(x <- 1:12, x-1, (y <- (x-5)^2), z <- y, z - 10 )) > > I don't see any way around the "mis-feature" that all "input" > expressions are in the end shown twice in the "output" (the > first time by showing the withAutoprint(...) call itself). > > The function *name* is "not bad" but also a bit longish; > maybe there are better ideas? (not longer, no "_" - I know this > is a matter of taste only) > > Martin > > > On Fri, Sep 2, 2016 at 4:56 AM, Martin Maechler > > > wrote: > > >> On R-help, with subject > >> '[R] source() does not include added code' > >> > >> > Joshua Ulrich > >> > on Wed, 31 Aug 2016 10:35:01 -0500 writes: > >> > >> > I have quantstrat installed and it works fine for me. If you're > >> > asking why the output of t(tradeStats('macross')) isn't being > >> printed, > >> > that's because of what's described in the first paragraph in the > >> > *Details* section of help("source"): > >> > >> > Note that running code via ‘source’ differs in a few respects from > >> > entering it at the R command line. Since expressions are not > >> > executed at the top level, auto-printing is not done. So you will > >> > need to include explicit ‘print’ calls for things you want to be > >> > printed (and remember that this includes plotting by ‘lattice’, > >> > FAQ Q7.22). > >> > >> > >> > >> > So you need: > >> > >> > print(t(tradeStats('macross'))) > >> > >> > if you want the output printed to the console. > >> > >> indeed, and "of course"" ;-) > >> > >> As my subject indicates, this is another case, where it would be > >> very convenient to have a function > >> > >> withAutoprint() > >> > >> so the OP could have (hopefully) have used > >> withAutoprint(source(..)) > >> though that would have been equivalent to the already nicely existing > >> > >> source(.., print.eval = TRUE) > >> > >> which works via the withVisible(.) utility that returns for each > >> 'expression' if it would auto print or not, and then does print (or > >> not) accordingly. > >> > >