I probably need to be more specific. What confuses me is not the use of substitute, but the parenthesis after the dots. It clearly works and I can make guesses as to why but it is definitely not obvious. The following function gives the same final result but I can understand what is happening. dots <- function (...) { exprs <- substitute(list(...)) as.list(exprs[-1]) } In the original, dots <- function(...) as.list(substitute(...())), Does ...() get parsed in a special way? Tim On Tue, 6 Oct 2020 at 05:30, Bert Gunter <bgunter.4567 at gmail.com> wrote:> > You need to understand what substitute() does -- see ?substitute and/or a tutorial on "R computing on the language" or similar. > > Here is a simple example that may clarify: > > > dots <- function(...) as.list(substitute(...())) > > dots(log(foo)) > [[1]] > log(foo) ## a call, a language object > > > dots2 <- function(...) as.list(...) > > dots2(log(foo)) > Error in as.list(...) : object 'foo' not found > ## substitute() does not evaluate its argument; as.list() does > > Cheers, > Bert Gunter > > "The trouble with having an open mind is that people keep coming along and sticking things into it." > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > On Mon, Oct 5, 2020 at 1:37 PM Tim Taylor <tim.taylor at hiddenelephants.co.uk> wrote: >> >> Could someone explain what is happening with the ...() of the >> following function: >> >> dots <- function(...) as.list(substitute(...())) >> >> I understand what I'm getting as a result but not why. ?dots and >> ?substitute leave me none the wiser. >> >> regards >> Tim >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> 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.
Hi Tim, I have also asked a similar question a couple of months ago, and someone else did the same recently, maybe on r-devel. We received no "official" response, but Deepayan Sarkar (R Core Team member) claimed that: " There is no documented reason for this to work (AFAIK), so again, I would guess this is a side-effect of the implementation, and not a API feature you should rely on. This is somewhat borne out by the following: > foo <- function(...) substitute({...()}) > foo(abc$de, fg[h], i) { pairlist(abc$de, fg[h], i) } > foo(abc$de, fg[h], , i) # add a missing argument for extra fun { as.pairlist(alist(abc$de, fg[h], , i)) } which is not something you would expect to see at the user level. So my recommendation: don't use ...() and pretend that you never discovered it in the first place. Use match.call() instead, as suggested by Serguei. [Disclaimer: I have no idea what is actually going on, so these are just guesses. There are some hints at https://cran.r-project.org/doc/manuals/r-devel/R-ints.html#Dot_002ddot_002ddot-arguments if you want to folllow up.] " Cheers, Denes On 10/6/20 8:38 AM, Tim Taylor wrote:> I probably need to be more specific. What confuses me is not the use > of substitute, but the parenthesis after the dots. It clearly works > and I can make guesses as to why but it is definitely not obvious. > The following function gives the same final result but I can > understand what is happening. > > dots <- function (...) { > exprs <- substitute(list(...)) > as.list(exprs[-1]) > } > > In the original, dots <- function(...) as.list(substitute(...())), > Does ...() get parsed in a special way? > > Tim > > On Tue, 6 Oct 2020 at 05:30, Bert Gunter <bgunter.4567 at gmail.com> wrote: >> >> You need to understand what substitute() does -- see ?substitute and/or a tutorial on "R computing on the language" or similar. >> >> Here is a simple example that may clarify: >> >>> dots <- function(...) as.list(substitute(...())) >>> dots(log(foo)) >> [[1]] >> log(foo) ## a call, a language object >> >>> dots2 <- function(...) as.list(...) >>> dots2(log(foo)) >> Error in as.list(...) : object 'foo' not found >> ## substitute() does not evaluate its argument; as.list() does >> >> Cheers, >> Bert Gunter >> >> "The trouble with having an open mind is that people keep coming along and sticking things into it." >> -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) >> >> >> On Mon, Oct 5, 2020 at 1:37 PM Tim Taylor <tim.taylor at hiddenelephants.co.uk> wrote: >>> >>> Could someone explain what is happening with the ...() of the >>> following function: >>> >>> dots <- function(...) as.list(substitute(...())) >>> >>> I understand what I'm getting as a result but not why. ?dots and >>> ?substitute leave me none the wiser. >>> >>> regards >>> Tim >>> >>> ______________________________________________ >>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >>> 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. > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > 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. >
Cheers Denes, That's useful to know. I'll stick with the match.call version instead. Interestingly I initially tried to post to R-devel (as I thought it may involve something internal) but was asked to post here instead. Best Tim On Tue, 6 Oct 2020 at 08:22, D?nes T?th <toth.denes at kogentum.hu> wrote:> > Hi Tim, > > I have also asked a similar question a couple of months ago, and someone > else did the same recently, maybe on r-devel. > > We received no "official" response, but Deepayan Sarkar (R Core Team > member) claimed that: > > " > There is no documented reason for this to work (AFAIK), so again, I > would guess this is a side-effect of the implementation, and not a API > feature you should rely on. This is somewhat borne out by the > following: > > > foo <- function(...) substitute({...()}) > > foo(abc$de, fg[h], i) > { > pairlist(abc$de, fg[h], i) > } > > foo(abc$de, fg[h], , i) # add a missing argument for extra fun > { > as.pairlist(alist(abc$de, fg[h], , i)) > } > > which is not something you would expect to see at the user level. So > my recommendation: don't use ...() and pretend that you never > discovered it in the first place. Use match.call() instead, as > suggested by Serguei. > > [Disclaimer: I have no idea what is actually going on, so these are > just guesses. There are some hints at > https://cran.r-project.org/doc/manuals/r-devel/R-ints.html#Dot_002ddot_002ddot-arguments > if you want to folllow up.] > " > > Cheers, > Denes > > > > > On 10/6/20 8:38 AM, Tim Taylor wrote: > > I probably need to be more specific. What confuses me is not the use > > of substitute, but the parenthesis after the dots. It clearly works > > and I can make guesses as to why but it is definitely not obvious. > > The following function gives the same final result but I can > > understand what is happening. > > > > dots <- function (...) { > > exprs <- substitute(list(...)) > > as.list(exprs[-1]) > > } > > > > In the original, dots <- function(...) as.list(substitute(...())), > > Does ...() get parsed in a special way? > > > > Tim > > > > On Tue, 6 Oct 2020 at 05:30, Bert Gunter <bgunter.4567 at gmail.com> wrote: > >> > >> You need to understand what substitute() does -- see ?substitute and/or a tutorial on "R computing on the language" or similar. > >> > >> Here is a simple example that may clarify: > >> > >>> dots <- function(...) as.list(substitute(...())) > >>> dots(log(foo)) > >> [[1]] > >> log(foo) ## a call, a language object > >> > >>> dots2 <- function(...) as.list(...) > >>> dots2(log(foo)) > >> Error in as.list(...) : object 'foo' not found > >> ## substitute() does not evaluate its argument; as.list() does > >> > >> Cheers, > >> Bert Gunter > >> > >> "The trouble with having an open mind is that people keep coming along and sticking things into it." > >> -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > >> > >> > >> On Mon, Oct 5, 2020 at 1:37 PM Tim Taylor <tim.taylor at hiddenelephants.co.uk> wrote: > >>> > >>> Could someone explain what is happening with the ...() of the > >>> following function: > >>> > >>> dots <- function(...) as.list(substitute(...())) > >>> > >>> I understand what I'm getting as a result but not why. ?dots and > >>> ?substitute leave me none the wiser. > >>> > >>> regards > >>> Tim > >>> > >>> ______________________________________________ > >>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > >>> 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. > > > > ______________________________________________ > > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > > 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. > >
> On 6 Oct 2020, at 09:22 , D?nes T?th <toth.denes at kogentum.hu> wrote: > > > foo <- function(...) substitute({...()}) > > foo(abc$de, fg[h], i) > { > pairlist(abc$de, fg[h], i) > } > > foo(abc$de, fg[h], , i) # add a missing argument for extra fun > { > as.pairlist(alist(abc$de, fg[h], , i)) > } >The 2nd one here is actually an artifact of deparse(). The result is still a pairlist, just one that pairlist(....) cannot reproduce:> e <- foo(abc$de, fg[h], , i) > e[[2]][[1]] abc$de [[2]] fg[h] [[3]] [[4]] i> deparse(e[[2]])[1] "as.pairlist(alist(abc$de, fg[h], , i))"> dput(e[[2]])as.pairlist(alist(abc$de, fg[h], , i))> mode(e[[2]])[1] "pairlist"> mode(e[[2]][[3]])[1] "name" I.e. the list in e[2] contains the missing indicator (an empty name). (I'm slightly puzzled why we need the curlies to trigger a deparse, though) -- Peter Dalgaard, Professor, Center for Statistics, Copenhagen Business School Solbjerg Plads 3, 2000 Frederiksberg, Denmark Phone: (+45)38153501 Office: A 4.23 Email: pd.mes at cbs.dk Priv: PDalgd at gmail.com