From henrik@bengt@@on @ending from gm@il@com  Mon Aug 13 11:18:59 2018
From: henrik@bengt@@on @ending from gm@il@com (Henrik Bengtsson)
Date: Mon, 13 Aug 2018 11:18:59 +0200
Subject: [Rd] substitute() on arguments in ellipsis ("dot dot dot")?
In-Reply-To: <CAJoaRhZDpA4PaaBRdoTCmpNSD4kjaN7+OVKwycW5Fue72R0-Pg@mail.gmail.com>
References: <CAFDcVCQppvvnXSgnO0CeG8Hpr7JWxFUMTnO7ORjK2JkUFKKWAw@mail.gmail.com>
 <601ad637-43cd-63e7-81b7-7b350bff5624@gmail.com>
 <CAJoaRhZDpA4PaaBRdoTCmpNSD4kjaN7+OVKwycW5Fue72R0-Pg@mail.gmail.com>
Message-ID: <CAFDcVCT2undj5oQHW4-wiuU2-F5jx9c6-z817rth08Bz3ycvGQ@mail.gmail.com>

Thanks all, this was very helpful.  Peter's finding - dots2() below -
is indeed interesting - I'd be curious to learn what goes on there.

The different alternatives perform approximately the same;

dots1 <- function(...) as.list(substitute(list(...)))[-1L]
dots2 <- function(...) as.list(substitute(...()))
dots3 <- function(...) match.call(expand.dots = FALSE)[["..."]]

stats <- microbenchmark::microbenchmark(
  dots1(1+2, "a", rnorm(3), stop("bang!")),
  dots2(1+2, "a", rnorm(3), stop("bang!")),
  dots3(1+2, "a", rnorm(3), stop("bang!")),
  times = 10e3
)
print(stats)
# Unit: microseconds
#                                        expr  min   lq mean median
uq  max neval
#  dots1(1 + 2, "a", rnorm(3), stop("bang!")) 2.14 2.45 3.04   2.58
2.73 1110 10000
#  dots2(1 + 2, "a", rnorm(3), stop("bang!")) 1.81 2.10 2.47   2.21
2.34 1626 10000
#  dots3(1 + 2, "a", rnorm(3), stop("bang!")) 2.59 2.98 3.36   3.15
3.31 1037 10000

/Henrik

On Mon, Aug 13, 2018 at 7:10 AM Peter Meilstrup
<peter.meilstrup at gmail.com> wrote:
>
> Interestingly,
>
>    as.list(substitute(...()))
>
> also works.
>
> On Sun, Aug 12, 2018 at 1:16 PM, Duncan Murdoch
> <murdoch.duncan at gmail.com> wrote:
> > On 12/08/2018 4:00 PM, Henrik Bengtsson wrote:
> >>
> >> Hi. For any number of *known* arguments, we can do:
> >>
> >> one <- function(a) list(a = substitute(a))
> >> two <- function(a, b) list(a = substitute(a), b = substitute(b))
> >>
> >> and so on. But how do I achieve the same when I have:
> >>
> >> dots <- function(...) list(???)
> >>
> >> I want to implement this such that I can do:
> >>
> >>> exprs <- dots(1+2)
> >>> str(exprs)
> >>
> >> List of 1
> >>   $ : language 1 + 2
> >>
> >> as well as:
> >>
> >>> exprs <- dots(1+2, "a", rnorm(3))
> >>> str(exprs)
> >>
> >> List of 3
> >>   $ : language 1 + 2
> >>   $ : chr "a"
> >>   $ : language rnorm(3)
> >>
> >> Is this possible to achieve using plain R code?
> >
> >
> > I think so.  substitute(list(...)) gives you a single expression containing
> > a call to list() with the unevaluated arguments; you can convert that to
> > what you want using something like
> >
> > dots <- function (...) {
> >   exprs <- substitute(list(...))
> >   as.list(exprs[-1])
> > }
> >
> > Duncan Murdoch
> >
> >
> > ______________________________________________
> > R-devel at r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] substitute() on arguments in ellipsis ("dot dot dot")?
Henrik Bengtsson