[Rd] Possible documentation problem/bug?
Deepayan Sarkar
deep@y@n@@@rk@r @end|ng |rom gm@||@com
Fri May 1 08:44:43 CEST 2020
On Thu, Apr 30, 2020 at 6:04 PM Dominic Littlewood
<11dlittlewood using gmail.com> wrote:
>
> It seems like there is no obvious way in the documentation to convert the
> expressions in the dots argument to a list without evaluating them. Say, if
> you want to have a function that prints all its arguments:
>
> > foo(abc$de, fg[h], i)
> abc$de
> fg[h]
> i
>
> ...then converting them to a list would be helpful.
> Using substitute(...) was the first thing I tried, but that only gives
> the *first* argument
Isn't that what you would expect anyway? substitute() takes two
arguments, the expression and an environment. You are giving it three.
Normally this should be an error:
foo <- function(a, b, c) substitute(a, b, c)
foo(abc$de, fg[h], i)
# Error in substitute(a, b, c) : unused argument (c)
Clearly ... is being handled in some special way so that we don't get
an error, but otherwise works as expected.
foo <- function(...) substitute(...)
foo(abc$de, fg[h], i)
# abc$de
I would consider this a side-effect of the implementation, and not
something you should rely on.
On the other hand, I would have expected the following to give
something sensible, and it does:
foo <- function(...) substitute({...})
foo(abc$de, fg[h], i)
# {
# abc$de
# fg[h]
# i
# }
as.character(foo(abc$de, fg[h], i))
# [1] "{" "abc$de" "fg[h]" "i"
> in dots. It turns out that there is a way to do this, using
> substitute(...()), but this does not appear to be in either the substitute or
> the dots help page.
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.]
-Deepayan
> In fact, there is a clue how to do this in the documentation, if you look
> closely. Let me quote the substitute page:
>
> "Substituting and quoting often cause confusion when the argument is
> expression(...). The result is a call to the expression constructor
> function and needs to be evaluated with eval to give the actual expression
> object."
>
> So this appears to give a way to turn the arguments into a list -
> eval(substitute(expression(...))). But that's quite long, and hard to
> understand if you just come across it in some code - why are we using eval
> here? why are we substituting expression? - and would definitely require an
> explanatory comment. If the user just wants to iterate over the arguments,
> substitute(...()) is better. In fact, you can get exactly the same effect
> as the above code using as.expression(substitute(...())). Should the
> documentation be updated?
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
More information about the R-devel
mailing list