substitute() on arguments in ellipsis ("dot dot dot")? Classic List Threaded 8 messages Open this post in threaded view
|

substitute() on arguments in ellipsis ("dot dot dot")?

 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? Thanks, Henrik ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

Re: substitute() on arguments in ellipsis ("dot dot dot")?

 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 ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

Re: substitute() on arguments in ellipsis ("dot dot dot")?

 In reply to this post by Henrik Bengtsson-5 On Sun, Aug 12, 2018 at 10:00 PM, Henrik Bengtsson <[hidden email]> 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? You could use match.call, for example:   dots <- function(...) match.call(expand.dots = FALSE)[['...']] Note that this returns a pairlist, so if you want an ordinary list you should wrap it in as.list() ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

Re: substitute() on arguments in ellipsis ("dot dot dot")?

 In reply to this post by Duncan Murdoch-2 Interestingly,    as.list(substitute(...())) also works. On Sun, Aug 12, 2018 at 1:16 PM, Duncan Murdoch <[hidden email]> 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 > > > ______________________________________________ > [hidden email] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

Re: substitute() on arguments in ellipsis ("dot dot dot")?

 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 <[hidden email]> wrote: > > Interestingly, > >    as.list(substitute(...())) > > also works. > > On Sun, Aug 12, 2018 at 1:16 PM, Duncan Murdoch > <[hidden email]> 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 > > > > > > ______________________________________________ > > [hidden email] mailing list > > https://stat.ethz.ch/mailman/listinfo/r-devel______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

Re: substitute() on arguments in ellipsis ("dot dot dot")?

 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 #>                                             #> 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 <[hidden email]> 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 > <[hidden email]> wrote: > > > > Interestingly, > > > >    as.list(substitute(...())) > > > > also works. > > > > On Sun, Aug 12, 2018 at 1:16 PM, Duncan Murdoch > > <[hidden email]> 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 > > > > > > > > > ______________________________________________ > > > [hidden email] mailing list > > > https://stat.ethz.ch/mailman/listinfo/r-devel> > ______________________________________________ > [hidden email] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel-- http://hadley.nz______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel