Skip to content

turning R expressions into functions?

9 messages · Jochen Voß, Hadley Wickham, S Ellison +2 more

#
Dear Dirk,
On Sat, Jun 30, 2012 at 01:28:13PM -0500, Dirk Eddelbuettel wrote:
Many thanks for pointing out these packages, I wasn't aware of these.
My own code (current version attached, comments would be very welcome)
is much more "chatty":
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
21 days later
#
Have a look at match.call.

Hadley
#
... 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}}
#
On Mon, Jul 23, 2012 at 2:12 PM, S Ellison <S.Ellison at lgcgroup.com> wrote:
But that evaluates them, which I don't think the original poster wanted.

Hadley
#
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
#
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 <wdunlap at tibco.com> wrote:

  
    
#
... 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 <bgunter at gene.com> 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
#
OK Bill, et, al:

I prefer your 3rd form buried in dotsArgs as:

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

##testit
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 <wdunlap at tibco.com> wrote: