[ please copy me on answers, since I am not subscribed to the list ] Dear all, I am trying to write an R function which uses system.time to determine which of a given list of R expressions executes fastest. To work around the limited resolution of system.time, I want to convert the given expressions into functions which execute the given expressions a fixed number of times. My current attempt is as follows: FuncIt <- function(k, expr) { k <- as.numeric(k) expr <- eval.parent(substitute(expr)) eval(substitute(function() { for (funcit.i in 1:k) { expr } })) } This works, but seems not very robust. My question: is there a better way of doing this? Here are some experiments. 1) good: If I run the following using "Rscript" test1 <- function(e1) { e1 <- substitute(e1) FuncIt(100, e1) } f <- test1(rnorm(1)) print(f) then I get the following output: function () { for (funcit.i in 1:100) { rnorm(1) } } <environment: 0x102260c28> This is what I want. But why do I need the extra "substitute" in test1? I only found by experiment that this is needed. 2) bad: If I try to call FuncIt directly, it fails: f <- FuncIt(100, rnorm(1)) print(f) has the output: function () { for (funcit.i in 1:100) { -0.763894772833099 } } <environment: 0x102265790> This is bad, since now 'rnorm(1)' already has been evaluated. How do I prevent this from happening, without breaking the good case 1 above? 3) ugly: If I run the same commands in the R gui on MacOS (R 2.15.1 released on 2012/06/22), I get different output:> source("/Users/voss/project/statcomp/test.R")function() { for (funcit.i in 1:k) { expr } } <environment: 0x19cc040> function() { for (funcit.i in 1:k) { expr } } <environment: 0x19bc884> This is on the same machine using (as far as I can tell) the same R engine. So why is the output different? Many thanks, Jochen -- http://seehuhn.de/
]On Sat, Jun 30, 2012 at 2:36 AM, Jochen Vo? <voss at seehuhn.de> wrote:> [ please copy me on answers, since I am not subscribed to the list ] > > Dear all, > > I am trying to write an R function which uses system.time > to determine which of a given list of R expressions executes > fastest. ?To work around the limited resolution of system.time, > I want to convert the given expressions into functions which > execute the given expressions a fixed number of times. > My current attempt is as follows: > > ?FuncIt <- function(k, expr) { > ? k <- as.numeric(k) > ? expr <- eval.parent(substitute(expr)) > ? eval(substitute(function() { for (funcit.i in 1:k) { expr } })) > ?} > > This works, but seems not very robust. > My question: is there a better way of doing this? > > Here are some experiments. > > 1) good: If I run the following using "Rscript" > > ?test1 <- function(e1) { > ? e1 <- substitute(e1) > ? FuncIt(100, e1) > ?} > > ?f <- test1(rnorm(1)) > ?print(f) > > then I get the following output: > > ?function () > ?{ > ? ? for (funcit.i in 1:100) { > ? ? ? ? rnorm(1) > ? ? } > ?} > ?<environment: 0x102260c28> > > This is what I want. ?But why do I need the extra "substitute" > in test1? ?I only found by experiment that this is needed.You don't. You need an extra quote() in the argument. That is, rnorm(1) is a call to the rnorm() function. Since R passes by value, the formal argument e1 is evaluated, returning a number, and that is what ends up in your code. If you want to pass a piece of unevaluated code to a function you should ideally use quote() or expression() to wrap it, so that it is not evaluated. You can get around this using substitute(), which extracts the unevaluated code from the formal argument, but it's probably a bad idea, since the user of the function should expect all the arguments to be evaluated.> > 2) bad: If I try to call FuncIt directly, it fails: > > ?f <- FuncIt(100, rnorm(1)) > ?print(f) > > has the output: > > ?function () > ?{ > ? ? for (funcit.i in 1:100) { > ? ? ? ? -0.763894772833099 > ? ? } > ?} > ?<environment: 0x102265790> > > This is bad, since now 'rnorm(1)' already has been > evaluated. ?How do I prevent this from happening, > without breaking the good case 1 above? >Use quote() or expression() rather than trying to trick the evaluator.> 3) ugly: If I run the same commands in the R gui on MacOS > (R 2.15.1 released on 2012/06/22), I get different output: > >> source("/Users/voss/project/statcomp/test.R") > ?function() { for (funcit.i in 1:k) { expr } } > ?<environment: 0x19cc040> > ?function() { for (funcit.i in 1:k) { expr } } > ?<environment: 0x19bc884> > > This is on the same machine using (as far as I can tell) the > same R engine. ?So why is the output different?The "ugly" formatting is how you formatted the code in the call to eval(), and the good formatting is how R would print it without any source constraints, so this is probably something to do with the keep.source= argument source(). -thomas -- Thomas Lumley Professor of Biostatistics University of Auckland
Look at the replicate function, it takes an expression (does not need a function) and runs that expression the specified number of times. Will that accomplish what you want without needing to worry about substitute, quote, eval, etc.? On Fri, Jun 29, 2012 at 11:36 AM, Jochen Vo? <voss at seehuhn.de> wrote:> [ please copy me on answers, since I am not subscribed to the list ] > > Dear all, > > I am trying to write an R function which uses system.time > to determine which of a given list of R expressions executes > fastest. To work around the limited resolution of system.time, > I want to convert the given expressions into functions which > execute the given expressions a fixed number of times. > My current attempt is as follows: > > FuncIt <- function(k, expr) { > k <- as.numeric(k) > expr <- eval.parent(substitute(expr)) > eval(substitute(function() { for (funcit.i in 1:k) { expr } })) > } > > This works, but seems not very robust. > My question: is there a better way of doing this? > > Here are some experiments. > > 1) good: If I run the following using "Rscript" > > test1 <- function(e1) { > e1 <- substitute(e1) > FuncIt(100, e1) > } > > f <- test1(rnorm(1)) > print(f) > > then I get the following output: > > function () > { > for (funcit.i in 1:100) { > rnorm(1) > } > } > <environment: 0x102260c28> > > This is what I want. But why do I need the extra "substitute" > in test1? I only found by experiment that this is needed. > > > 2) bad: If I try to call FuncIt directly, it fails: > > f <- FuncIt(100, rnorm(1)) > print(f) > > has the output: > > function () > { > for (funcit.i in 1:100) { > -0.763894772833099 > } > } > <environment: 0x102265790> > > This is bad, since now 'rnorm(1)' already has been > evaluated. How do I prevent this from happening, > without breaking the good case 1 above? > > > 3) ugly: If I run the same commands in the R gui on MacOS > (R 2.15.1 released on 2012/06/22), I get different output: > >> source("/Users/voss/project/statcomp/test.R") > function() { for (funcit.i in 1:k) { expr } } > <environment: 0x19cc040> > function() { for (funcit.i in 1:k) { expr } } > <environment: 0x19bc884> > > This is on the same machine using (as far as I can tell) the > same R engine. So why is the output different? > > > Many thanks, > Jochen > -- > http://seehuhn.de/ > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.-- Gregory (Greg) L. Snow Ph.D. 538280 at gmail.com