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