[Rd] length of `...`
Hervé Pagès
hp@ge@ @ending from fredhutch@org
Tue May 8 18:04:58 CEST 2018
Thanks Martin for the clarifications. H.
On 05/04/2018 06:02 AM, Martin Maechler wrote:
>>>>>> 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://urldefense.proofpoint.com/v2/url?u=https-3A__stat.ethz.ch_mailman_listinfo_r-2Ddevel&d=DwIDAw&c=eRAMFD45gAfqt84VtBcfhQ&r=BK7q3XeAvimeWdGbWY_wJYbW0WYiZvSXAJJKaaPhzWA&m=BGlRjScM4h5whbLQ891iVxeMRA4PY37vwG3cnC5kuDI&s=_XZhh9pIVv0VBjUYXBgW39dss7YCGQE3XCArLMDfvDo&e=
>
--
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
More information about the R-devel
mailing list