[Rd] length of `...`

Duncan Murdoch murdoch@dunc@n @ending from gm@il@com
Thu May 3 17:18:52 CEST 2018


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.

Duncan Murdoch




More information about the R-devel mailing list