[Rd] length of `...`
Duncan Murdoch
murdoch@dunc@n @ending from gm@il@com
Thu May 3 18:50:37 CEST 2018
On 03/05/2018 11:18 AM, Duncan Murdoch wrote:
> On 03/05/2018 11:01 AM, William Dunlap via R-devel wrote:
>> In R-3.5.0 you can use ...length():
>> > f <- function(..., n) ...length()
>> > f(stop("one"), stop("two"), stop("three"), n=7)
>> [1] 3
>>
>> Prior to that substitute() is the way to go
>> > g <- function(..., n) length(substitute(...()))
>> > g(stop("one"), stop("two"), stop("three"), n=7)
>> [1] 3
>>
>> R-3.5.0 also has the ...elt(n) function, which returns
>> the evaluated n'th entry in ... , without evaluating the
>> other ... entries.
>> > fn <- function(..., n) ...elt(n)
>> > fn(stop("one"), 3*5, stop("three"), n=2)
>> [1] 15
>>
>> Prior to 3.5.0, eval the appropriate component of the output
>> of substitute() in the appropriate environment:
>> > gn <- function(..., n) {
>> + nthExpr <- substitute(...())[[n]]
>> + eval(nthExpr, envir=parent.frame())
>> + }
>> > gn(stop("one"), environment(), stop("two"), n=2)
>> <environment: R_GlobalEnv>
>>
>
> Bill, the last of these doesn't quite work, because ... can be passed
> down through a string of callers. You don't necessarily want to
> evaluate it in the parent.frame(). For example:
>
> x <- "global"
> f <- function(...) {
> x <- "f"
> g(...)
> }
> g <- function(...) {
> firstExpr <- substitute(...())[[1]]
> c(list(...)[[1]], eval(firstExpr, envir = parent.frame()))
> }
>
> Calling g(x) correctly prints "global" twice, but calling f(x)
> incorrectly prints
>
> [1] "global" "f"
>
> You can get the first element of ... without evaluating the rest using
> ..1, but I don't know a way to do this for general n in pre-3.5.0 base R.
Here's a way to do that:
eval(as.name(paste0("..", n)))
I was surprised this worked for n > 9, but it does. Looking at the
source, I think the largest legal value for n is huge; you'd hit other
limits long before n was too big.
Duncan Murdoch
More information about the R-devel
mailing list