>>>>> Hervé Pagès <hpa...@fredhutch.org> >>>>> on Thu, 3 May 2018 08:55:20 -0700 writes:
> Hi, > It would be great if one of the experts could comment on the > difference between Hadley's dotlength and ...length? The fact > that someone bothered to implement a new primitive for that > when there seems to be a very simple and straightforward R-only > solution suggests that there might be some gotchas/pitfalls with > the R-only solution. Namely > dotlength <- function(...) nargs() > (This is subtly different from calling nargs() directly as it will > only count the elements in ...) > Hadley Well, I was the "someone". In the past I had seen (and used myself) length(list(...)) and of course that was not usable. I knew of some substitute() / match.call() tricks [but I think did not know Bill's cute substitute(...()) !] at the time, but found them too esoteric. Aditionally and importantly, ...length() and ..elt(n) were developed "synchronously", and the R-substitutes for ..elt() definitely are less trivial (I did not find one at the time), as Duncan's example to Bill's proposal has shown, so I had looked at .Primitive() solutions of both. In hindsight I should have asked here for advice, but may at the time I had been a bit frustrated by the results of some of my RFCs ((nothing specific in mind !)) But __if__ there's really no example where current (3.5.0 and newer) ...length() differs from Hadley's dotlength() I'd vert happy to replace ...length 's C based definition by Hadley's beautiful minimal solution. Martin > On 05/03/2018 08:34 AM, Hadley Wickham wrote: >> On Thu, May 3, 2018 at 8:18 AM, Duncan Murdoch <murdoch.dun...@gmail.com> 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. >> >> If you don't mind using a package: >> >> # works with R 3.1 and up >> library(rlang) >> >> x <- "global" >> f <- function(...) { >> x <- "f" >> g(...) >> } >> g <- function(...) { >> dots <- enquos(...) >> eval_tidy(dots[[1]]) >> } >> >> f(x, stop("!")) >> #> [1] "global" >> g(x, stop("!")) >> #> [1] "global" >> >> Hadley >> > -- > Hervé Pagès > Program in Computational Biology > Division of Public Health Sciences > Fred Hutchinson Cancer Research Center > 1100 Fairview Ave. N, M1-B514 > P.O. Box 19024 > Seattle, WA 98109-1024 > E-mail: hpa...@fredhutch.org > Phone: (206) 667-5791 > Fax: (206) 667-1319 > ______________________________________________ > 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