[Rd] length of `...`
Martin Maechler
maechler at stat.math.ethz.ch
Fri May 4 15:02:22 CEST 2018
>>>>> Hervé Pagès <hpages at 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.duncan at 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: hpages at fredhutch.org
> Phone: (206) 667-5791
> Fax: (206) 667-1319
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
More information about the R-devel
mailing list