From j@me@@f@he@ter @ending from gm@il@com  Wed Aug 15 15:04:59 2018
From: j@me@@f@he@ter @ending from gm@il@com (Jim Hester)
Date: Wed, 15 Aug 2018 09:04:59 -0400
Subject: [Rd] substitute() on arguments in ellipsis ("dot dot dot")?
In-Reply-To: <CABdHhvFeeAds1kYqw+8MZXUjfArKzFAOpFVOAeuDt1pFik0sdA@mail.gmail.com>
References: <CAFDcVCQppvvnXSgnO0CeG8Hpr7JWxFUMTnO7ORjK2JkUFKKWAw@mail.gmail.com>
 <601ad637-43cd-63e7-81b7-7b350bff5624@gmail.com>
 <CAJoaRhZDpA4PaaBRdoTCmpNSD4kjaN7+OVKwycW5Fue72R0-Pg@mail.gmail.com>
 <CAFDcVCT2undj5oQHW4-wiuU2-F5jx9c6-z817rth08Bz3ycvGQ@mail.gmail.com>
 <CABdHhvFeeAds1kYqw+8MZXUjfArKzFAOpFVOAeuDt1pFik0sdA@mail.gmail.com>
Message-ID: <CAD6tx95SP4bXeZeFLcxk9grn8FZpuMU5Vft0b77g8Dd7g3E-dA@mail.gmail.com>

Assuming you are fine with a pairlist instead of a list avoiding the
`as.list()` call for dots2 saves a reasonable amount of time and makes it
clearly the fastest.

library(rlang)

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

bench::mark(
  dots1(1+2, "a", rnorm(3), stop("bang!")),
  dots2(1+2, "a", rnorm(3), stop("bang!")),
  dots2.5(1+2, "a", rnorm(3), stop("bang!")),
  dots3(1+2, "a", rnorm(3), stop("bang!")),
  dots4(1+2, "a", rnorm(3), stop("bang!")),
  check = FALSE
)[1:4]
#> # A tibble: 5 x 4
#>   expression                                         min     mean
 median
#>   <chr>                                         <bch:tm> <bch:tm>
<bch:tm>
#> 1 "dots1(1 + 2, \"a\", rnorm(3), stop(\"bang!\?   2.38?s   5.63?s
 2.89?s
#> 2 "dots2(1 + 2, \"a\", rnorm(3), stop(\"bang!\?   2.07?s    3.1?s
2.6?s
#> 3 "dots2.5(1 + 2, \"a\", rnorm(3), stop(\"bang?    471ns  789.5ns
638ns
#> 4 "dots3(1 + 2, \"a\", rnorm(3), stop(\"bang!\?   3.17?s   4.83?s
 4.22?s
#> 5 "dots4(1 + 2, \"a\", rnorm(3), stop(\"bang!\?   3.16?s   4.43?s
 3.87?s


On Mon, Aug 13, 2018 at 7:59 PM Hadley Wickham <h.wickham at gmail.com> wrote:

> Since you're already using bang-bang ;)
>
> library(rlang)
>
> dots1 <- function(...) as.list(substitute(list(...)))[-1L]
> dots2 <- function(...) as.list(substitute(...()))
> dots3 <- function(...) match.call(expand.dots = FALSE)[["..."]]
> dots4 <- function(...) exprs(...)
>
> bench::mark(
>   dots1(1+2, "a", rnorm(3), stop("bang!")),
>   dots2(1+2, "a", rnorm(3), stop("bang!")),
>   dots3(1+2, "a", rnorm(3), stop("bang!")),
>   dots4(1+2, "a", rnorm(3), stop("bang!")),
>   check = FALSE
> )[1:4]
> #> # A tibble: 4 x 4
> #>   expression                                          min     mean
> median
> #>   <chr>                                          <bch:tm> <bch:tm>
> <bch:t>
> #> 1 "dots1(1 + 2, \"a\", rnorm(3), stop(\"bang!\"?   3.23?s   4.15?s
> 3.81?s
> #> 2 "dots2(1 + 2, \"a\", rnorm(3), stop(\"bang!\"?   2.72?s   4.48?s
> 3.37?s
> #> 3 "dots3(1 + 2, \"a\", rnorm(3), stop(\"bang!\"?   4.06?s   4.94?s
> 4.69?s
> #> 4 "dots4(1 + 2, \"a\", rnorm(3), stop(\"bang!\"?   3.92?s    4.9?s
> 4.46?s
>
>
> On Mon, Aug 13, 2018 at 4:19 AM Henrik Bengtsson
> <henrik.bengtsson at gmail.com> wrote:
> >
> > 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
> >
> > ______________________________________________
> > R-devel at r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
>
>
>
> --
> http://hadley.nz
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

	[[alternative HTML version deleted]]



[Rd] substitute() on arguments in ellipsis ("dot dot dot")?
Jim Hester