Quantcast

turning R expressions into functions?

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

turning R expressions into functions?

Jochen Voß
[ 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/

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Thomas Lumley-2
]On Sat, Jun 30, 2012 at 2:36 AM, Jochen Voß <[hidden email]> 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

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

glsnow
In reply to this post by Jochen Voß
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ß <[hidden email]> 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/
>
> ______________________________________________
> [hidden email] 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.
[hidden email]

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Dirk Eddelbuettel

On 30 June 2012 at 11:39, Greg Snow wrote:
| 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.?

And also look at the existing benchmark packages 'rbenchmark' and
'microbenchmark':

   R> library(microbenchmark)
   R> x <- 5; microbenchmark( 1/x, x^-1 )
   Unit: nanoseconds
     expr min    lq median    uq  max
   1  1/x 296 322.5    341 364.0 6298
   2 x^-1 516 548.5    570 591.5 5422
   R>

Dirk

--
Dirk Eddelbuettel | [hidden email] | http://dirk.eddelbuettel.com

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Jochen Voß
In reply to this post by Thomas Lumley-2
Dear Thomas,

Many thanks for your answer.

On Sat, Jun 30, 2012 at 10:22:52AM +0900, Thomas Lumley wrote:

> > 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.
> [...]
> 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.

I want my final function to work like system.time, i.e.
the user should not have to type "quote()" all the time
when calling the top-level function of my measuring
mechanism.

Is there a way to do the quoting inside the top-level function
call?

Many thanks,
Jochen Voss
--
http://seehuhn.de/

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Jochen Voß
In reply to this post by glsnow
Dear Greg,

many thanks for your anwer.

On Sat, Jun 30, 2012 at 11:39:07AM -0600, Greg Snow wrote:
> 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.?

Yes, this is very similar to what I want to achieve.
One of the main differences is that 'replicate' builds
up a list of all call results, and for my measurements
I want to avoid the resulting (time and memory) overhead.
But I did look at the implementation of 'replicate'
and this is where I took the trick of using
eval.parent and substitute from.

All the best,
Jochen
--
http://seehuhn.de/

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Jochen Voß
In reply to this post by Dirk Eddelbuettel
Dear Dirk,

On Sat, Jun 30, 2012 at 01:28:13PM -0500, Dirk Eddelbuettel wrote:
> And also look at the existing benchmark packages 'rbenchmark' and
> 'microbenchmark':

Many thanks for pointing out these packages, I wasn't aware of these.

>    R> library(microbenchmark)
>    R> x <- 5; microbenchmark( 1/x, x^-1 )
>    Unit: nanoseconds
>      expr min    lq median    uq  max
>    1  1/x 296 322.5    341 364.0 6298
>    2 x^-1 516 548.5    570 591.5 5422

My own code (current version attached, comments would be very welcome)
is much more "chatty":

>    R> source("timeit.R")
>    R> x <- 5; TimeIt(1/x, x^-1)
>    tuning ...
>    measuring 10*1466753 samples for each expression ...
>      |======================================================================| 100%
>    
>    execution time comparison:
>    1/x    (0.000571 ± 1.48e-05) ms/call
>    x^-1   (0.000864 ± 9.69e-06) ms/call
>    CI for difference: [-0.00031, -0.000275] ms/call
>    
>    '1/x' is about 33.9% faster (p=2.75e-11)
One of the things I would love to add to my package would be the
ability to compare more than two expressions in one call.  But
unfortunately, I haven't found out so far whether (and if so, how) it
is possible to extract the elements of a "..." object without
evaluating them.

Many thanks,
Jochen
--
http://seehuhn.de/

______________________________________________
[hidden email] 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.

timeit.R (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Hadley Wickham-2
> One of the things I would love to add to my package would be the
> ability to compare more than two expressions in one call.  But
> unfortunately, I haven't found out so far whether (and if so, how) it
> is possible to extract the elements of a "..." object without
> evaluating them.

Have a look at match.call.

Hadley

--
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

S Ellison-2
>> One of the things I would love to add to my package would be the
>> ability to compare more than two expressions in one call.  But
>> unfortunately, I haven't found out so far whether (and if so, how) it
>> is possible to extract the elements of a "..." object without
>> evaluating them.
>
>Have a look at match.call.

... or use
dotlist <- list(...)

to get a list of everything included in ...

S Ellison

*******************************************************************
This email and any attachments are confidential. Any use...{{dropped:8}}

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Hadley Wickham-2
On Mon, Jul 23, 2012 at 2:12 PM, S Ellison <[hidden email]> wrote:

>>> One of the things I would love to add to my package would be the
>>> ability to compare more than two expressions in one call.  But
>>> unfortunately, I haven't found out so far whether (and if so, how) it
>>> is possible to extract the elements of a "..." object without
>>> evaluating them.
>>
>>Have a look at match.call.
>
> ... or use
> dotlist <- list(...)
>
> to get a list of everything included in ...

But that evaluates them, which I don't think the original poster wanted.

Hadley

--
Assistant Professor / Dobelman Family Junior Chair
Department of Statistics / Rice University
http://had.co.nz/

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

William Dunlap
In reply to this post by S Ellison-2
list(...) evaluates the things in ...
E.g.,
   > f0 <- function(x, ...) list(...)
   > f0(1, warning("Hmm"), stop("Oops"), cat("some output\n"))[[2]]
   Error in f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Oops
   In addition: Warning message:
   In f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Hmm

You can use the odd idiom substitute(...()) to get the unevaluated ... arguments:
   > f1 <- function(x, ...) substitute(...())
   > f1(1, warning("Hmm"), stop("Oops"), cat("some output\n"))
   [[1]]
   warning("Hmm")

   [[2]]
   stop("Oops")

   [[3]]
   cat("some output\n")


Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com


> -----Original Message-----
> From: [hidden email] [mailto:[hidden email]] On
> Behalf Of S Ellison
> Sent: Monday, July 23, 2012 2:12 PM
> To: Jochen Voß
> Cc: [hidden email]
> Subject: Re: [R] turning R expressions into functions?
>
> >> One of the things I would love to add to my package would be the
> >> ability to compare more than two expressions in one call.  But
> >> unfortunately, I haven't found out so far whether (and if so, how) it
> >> is possible to extract the elements of a "..." object without
> >> evaluating them.
> >
> >Have a look at match.call.
>
> ... or use
> dotlist <- list(...)
>
> to get a list of everything included in ...
>
> S Ellison
>
> *****************************************************************
> **
> This email and any attachments are confidential. Any use...{{dropped:8}}
>
> ______________________________________________
> [hidden email] 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.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Bert Gunter
Bill:

Is there some reason to prefer your "odd idiom" to match.call, perhaps
as as.list(match.call()), as proposed by Hadley?

-- Bert

On Mon, Jul 23, 2012 at 2:25 PM, William Dunlap <[hidden email]> wrote:

> list(...) evaluates the things in ...
> E.g.,
>    > f0 <- function(x, ...) list(...)
>    > f0(1, warning("Hmm"), stop("Oops"), cat("some output\n"))[[2]]
>    Error in f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Oops
>    In addition: Warning message:
>    In f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Hmm
>
> You can use the odd idiom substitute(...()) to get the unevaluated ... arguments:
>    > f1 <- function(x, ...) substitute(...())
>    > f1(1, warning("Hmm"), stop("Oops"), cat("some output\n"))
>    [[1]]
>    warning("Hmm")
>
>    [[2]]
>    stop("Oops")
>
>    [[3]]
>    cat("some output\n")
>
>
> Bill Dunlap
> Spotfire, TIBCO Software
> wdunlap tibco.com
>
>
>> -----Original Message-----
>> From: [hidden email] [mailto:[hidden email]] On
>> Behalf Of S Ellison
>> Sent: Monday, July 23, 2012 2:12 PM
>> To: Jochen Voß
>> Cc: [hidden email]
>> Subject: Re: [R] turning R expressions into functions?
>>
>> >> One of the things I would love to add to my package would be the
>> >> ability to compare more than two expressions in one call.  But
>> >> unfortunately, I haven't found out so far whether (and if so, how) it
>> >> is possible to extract the elements of a "..." object without
>> >> evaluating them.
>> >
>> >Have a look at match.call.
>>
>> ... or use
>> dotlist <- list(...)
>>
>> to get a list of everything included in ...
>>
>> S Ellison
>>
>> *****************************************************************
>> **
>> This email and any attachments are confidential. Any use...{{dropped:8}}
>>
>> ______________________________________________
>> [hidden email] 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.
>
> ______________________________________________
> [hidden email] 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.



--

Bert Gunter
Genentech Nonclinical Biostatistics

Internal Contact Info:
Phone: 467-7374
Website:
http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Bert Gunter
... or better still, the idiom used in update.default:

match.call(expand.dots=FALSE)$...

?
-- Bert

On Mon, Jul 23, 2012 at 2:45 PM, Bert Gunter <[hidden email]> wrote:

> Bill:
>
> Is there some reason to prefer your "odd idiom" to match.call, perhaps
> as as.list(match.call()), as proposed by Hadley?
>
> -- Bert
>
> On Mon, Jul 23, 2012 at 2:25 PM, William Dunlap <[hidden email]> wrote:
>> list(...) evaluates the things in ...
>> E.g.,
>>    > f0 <- function(x, ...) list(...)
>>    > f0(1, warning("Hmm"), stop("Oops"), cat("some output\n"))[[2]]
>>    Error in f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Oops
>>    In addition: Warning message:
>>    In f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Hmm
>>
>> You can use the odd idiom substitute(...()) to get the unevaluated ... arguments:
>>    > f1 <- function(x, ...) substitute(...())
>>    > f1(1, warning("Hmm"), stop("Oops"), cat("some output\n"))
>>    [[1]]
>>    warning("Hmm")
>>
>>    [[2]]
>>    stop("Oops")
>>
>>    [[3]]
>>    cat("some output\n")
>>
>>
>> Bill Dunlap
>> Spotfire, TIBCO Software
>> wdunlap tibco.com
>>
>>
>>> -----Original Message-----
>>> From: [hidden email] [mailto:[hidden email]] On
>>> Behalf Of S Ellison
>>> Sent: Monday, July 23, 2012 2:12 PM
>>> To: Jochen Voß
>>> Cc: [hidden email]
>>> Subject: Re: [R] turning R expressions into functions?
>>>
>>> >> One of the things I would love to add to my package would be the
>>> >> ability to compare more than two expressions in one call.  But
>>> >> unfortunately, I haven't found out so far whether (and if so, how) it
>>> >> is possible to extract the elements of a "..." object without
>>> >> evaluating them.
>>> >
>>> >Have a look at match.call.
>>>
>>> ... or use
>>> dotlist <- list(...)
>>>
>>> to get a list of everything included in ...
>>>
>>> S Ellison
>>>
>>> *****************************************************************
>>> **
>>> This email and any attachments are confidential. Any use...{{dropped:8}}
>>>
>>> ______________________________________________
>>> [hidden email] 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.
>>
>> ______________________________________________
>> [hidden email] 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.
>
>
>
> --
>
> Bert Gunter
> Genentech Nonclinical Biostatistics
>
> Internal Contact Info:
> Phone: 467-7374
> Website:
> http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm



--

Bert Gunter
Genentech Nonclinical Biostatistics

Internal Contact Info:
Phone: 467-7374
Website:
http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

William Dunlap
In reply to this post by Bert Gunter
I tend not to use match.call for this because it feels like I'm repeating
work (argument matching) that has already been done.  Also, match.call's
output needs to be processed a bit to get the expressions.

The following 2 functions give the same results, a "pairlist" of the unevaluated
arguments matching the "..." in the function definition.
   f1 <- function(x, ..., atEnd) substitute(...())
   f2 <- function(x, ..., atEnd) match.call(expand.dots=FALSE)$...
E.g.,
  > str(f1(1, stop("don't evaluate me!"), Log=log(-10:1), atEnd=Inf))
  Dotted pair list of 2
   $    : language stop("don't evaluate me!")
   $ Log: language log(-10:1)
  > str(f2(1, stop("don't evaluate me!"), Log=log(-10:1), atEnd=Inf))
  Dotted pair list of 2
   $    : language stop("don't evaluate me!")
   $ Log: language log(-10:1)
The former appears to be about 3 times as fast as the latter, but you need
to run it a lot of times (>10^4) to see the difference.  There may be a bigger
speedup if there are lots of non-"..." arguments, but I haven't tested that.
 
I also use the following, which works in both S+ and R:
   > f3 <- function(x, ..., atEnd) as.list(substitute(junk(...)))[-1]
   > str(f3(1, stop("don't evaluate me!"), Log=log(-10:1), atEnd=Inf))
   List of 2
    $    : language stop("don't evaluate me!")
    $ Log: language log(-10:1)

It is probably best to bury this in a utility function with an intuitive name instead
of trying to remember the idioms.  Perhaps there already is one.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com


> -----Original Message-----
> From: Bert Gunter [mailto:[hidden email]]
> Sent: Monday, July 23, 2012 2:45 PM
> To: William Dunlap
> Cc: S Ellison; Jochen Voß; [hidden email]
> Subject: Re: [R] turning R expressions into functions?
>
> Bill:
>
> Is there some reason to prefer your "odd idiom" to match.call, perhaps
> as as.list(match.call()), as proposed by Hadley?
>
> -- Bert
>
> On Mon, Jul 23, 2012 at 2:25 PM, William Dunlap <[hidden email]> wrote:
> > list(...) evaluates the things in ...
> > E.g.,
> >    > f0 <- function(x, ...) list(...)
> >    > f0(1, warning("Hmm"), stop("Oops"), cat("some output\n"))[[2]]
> >    Error in f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Oops
> >    In addition: Warning message:
> >    In f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Hmm
> >
> > You can use the odd idiom substitute(...()) to get the unevaluated ... arguments:
> >    > f1 <- function(x, ...) substitute(...())
> >    > f1(1, warning("Hmm"), stop("Oops"), cat("some output\n"))
> >    [[1]]
> >    warning("Hmm")
> >
> >    [[2]]
> >    stop("Oops")
> >
> >    [[3]]
> >    cat("some output\n")
> >
> >
> > Bill Dunlap
> > Spotfire, TIBCO Software
> > wdunlap tibco.com
> >
> >
> >> -----Original Message-----
> >> From: [hidden email] [mailto:[hidden email]] On
> >> Behalf Of S Ellison
> >> Sent: Monday, July 23, 2012 2:12 PM
> >> To: Jochen Voß
> >> Cc: [hidden email]
> >> Subject: Re: [R] turning R expressions into functions?
> >>
> >> >> One of the things I would love to add to my package would be the
> >> >> ability to compare more than two expressions in one call.  But
> >> >> unfortunately, I haven't found out so far whether (and if so, how) it
> >> >> is possible to extract the elements of a "..." object without
> >> >> evaluating them.
> >> >
> >> >Have a look at match.call.
> >>
> >> ... or use
> >> dotlist <- list(...)
> >>
> >> to get a list of everything included in ...
> >>
> >> S Ellison
> >>
> >>
> *****************************************************************
> >> **
> >> This email and any attachments are confidential. Any use...{{dropped:8}}
> >>
> >> ______________________________________________
> >> [hidden email] 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.
> >
> > ______________________________________________
> > [hidden email] 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.
>
>
>
> --
>
> Bert Gunter
> Genentech Nonclinical Biostatistics
>
> Internal Contact Info:
> Phone: 467-7374
> Website:
> http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-
> biostatistics/pdb-ncb-home.htm
______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Bert Gunter
OK Bill, et, al:

I prefer your 3rd form buried in dotsArgs as:

dotsArgs <- function()as.list(substitute((...),env=parent.frame()))[-1]

##testit
> f <- function(x, ..., atEnd) dotsArgs()
>  str(f(1, stop("don't evaluate me!"), Log=log(-10:1), atEnd=Inf))
List of 2
 $    : language stop("don't evaluate me!")
 $ Log: language log(-10:1)

Let me know if you see any problems (if you care to bother with it)

-- Bert

On Mon, Jul 23, 2012 at 3:04 PM, William Dunlap <[hidden email]> wrote:

> I tend not to use match.call for this because it feels like I'm repeating
> work (argument matching) that has already been done.  Also, match.call's
> output needs to be processed a bit to get the expressions.
>
> The following 2 functions give the same results, a "pairlist" of the unevaluated
> arguments matching the "..." in the function definition.
>    f1 <- function(x, ..., atEnd) substitute(...())
>    f2 <- function(x, ..., atEnd) match.call(expand.dots=FALSE)$...
> E.g.,
>   > str(f1(1, stop("don't evaluate me!"), Log=log(-10:1), atEnd=Inf))
>   Dotted pair list of 2
>    $    : language stop("don't evaluate me!")
>    $ Log: language log(-10:1)
>   > str(f2(1, stop("don't evaluate me!"), Log=log(-10:1), atEnd=Inf))
>   Dotted pair list of 2
>    $    : language stop("don't evaluate me!")
>    $ Log: language log(-10:1)
> The former appears to be about 3 times as fast as the latter, but you need
> to run it a lot of times (>10^4) to see the difference.  There may be a bigger
> speedup if there are lots of non-"..." arguments, but I haven't tested that.
>
> I also use the following, which works in both S+ and R:
>    > f3 <- function(x, ..., atEnd) as.list(substitute(junk(...)))[-1]
>    > str(f3(1, stop("don't evaluate me!"), Log=log(-10:1), atEnd=Inf))
>    List of 2
>     $    : language stop("don't evaluate me!")
>     $ Log: language log(-10:1)
>
> It is probably best to bury this in a utility function with an intuitive name instead
> of trying to remember the idioms.  Perhaps there already is one.
>
> Bill Dunlap
> Spotfire, TIBCO Software
> wdunlap tibco.com
>
>
>> -----Original Message-----
>> From: Bert Gunter [mailto:[hidden email]]
>> Sent: Monday, July 23, 2012 2:45 PM
>> To: William Dunlap
>> Cc: S Ellison; Jochen Voß; [hidden email]
>> Subject: Re: [R] turning R expressions into functions?
>>
>> Bill:
>>
>> Is there some reason to prefer your "odd idiom" to match.call, perhaps
>> as as.list(match.call()), as proposed by Hadley?
>>
>> -- Bert
>>
>> On Mon, Jul 23, 2012 at 2:25 PM, William Dunlap <[hidden email]> wrote:
>> > list(...) evaluates the things in ...
>> > E.g.,
>> >    > f0 <- function(x, ...) list(...)
>> >    > f0(1, warning("Hmm"), stop("Oops"), cat("some output\n"))[[2]]
>> >    Error in f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Oops
>> >    In addition: Warning message:
>> >    In f0(1, warning("Hmm"), stop("Oops"), cat("some output\n")) : Hmm
>> >
>> > You can use the odd idiom substitute(...()) to get the unevaluated ... arguments:
>> >    > f1 <- function(x, ...) substitute(...())
>> >    > f1(1, warning("Hmm"), stop("Oops"), cat("some output\n"))
>> >    [[1]]
>> >    warning("Hmm")
>> >
>> >    [[2]]
>> >    stop("Oops")
>> >
>> >    [[3]]
>> >    cat("some output\n")
>> >
>> >
>> > Bill Dunlap
>> > Spotfire, TIBCO Software
>> > wdunlap tibco.com
>> >
>> >
>> >> -----Original Message-----
>> >> From: [hidden email] [mailto:[hidden email]] On
>> >> Behalf Of S Ellison
>> >> Sent: Monday, July 23, 2012 2:12 PM
>> >> To: Jochen Voß
>> >> Cc: [hidden email]
>> >> Subject: Re: [R] turning R expressions into functions?
>> >>
>> >> >> One of the things I would love to add to my package would be the
>> >> >> ability to compare more than two expressions in one call.  But
>> >> >> unfortunately, I haven't found out so far whether (and if so, how) it
>> >> >> is possible to extract the elements of a "..." object without
>> >> >> evaluating them.
>> >> >
>> >> >Have a look at match.call.
>> >>
>> >> ... or use
>> >> dotlist <- list(...)
>> >>
>> >> to get a list of everything included in ...
>> >>
>> >> S Ellison
>> >>
>> >>
>> *****************************************************************
>> >> **
>> >> This email and any attachments are confidential. Any use...{{dropped:8}}
>> >>
>> >> ______________________________________________
>> >> [hidden email] 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.
>> >
>> > ______________________________________________
>> > [hidden email] 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.
>>
>>
>>
>> --
>>
>> Bert Gunter
>> Genentech Nonclinical Biostatistics
>>
>> Internal Contact Info:
>> Phone: 467-7374
>> Website:
>> http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-
>> biostatistics/pdb-ncb-home.htm



--

Bert Gunter
Genentech Nonclinical Biostatistics

Internal Contact Info:
Phone: 467-7374
Website:
http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: turning R expressions into functions?

Jochen Voß
In reply to this post by William Dunlap
Dear all,

Sorry for my slow answer, and thanks for all the suggestion.

On 23 Jul 2012, at 22:25, William Dunlap <[hidden email]> wrote:
> You can use the odd idiom substitute(...()) to get the unevaluated ... arguments:
>> f1 <- function(x, ...) substitute(...())
>> f1(1, warning("Hmm"), stop("Oops"), cat("some output\n"))

This is what I finally settled on using.

Many thanks,
Jochen
--
http://seehuhn.de/

______________________________________________
[hidden email] 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.
Loading...