On Thu, Apr 30, 2020 at 6:04 PM Dominic Littlewood <11dlittlew...@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@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel