[Rd] length of `...`
Joris Meys
jorismeys at gmail.com
Fri May 4 15:37:27 CEST 2018
The one difference I see, is the necessity to pass the dots to the function
dotlength :
dotlength <- function(...) nargs()
myfun <- function(..., someArg = 1){
n1 <- ...length()
n2 <- dotlength()
n3 <- dotlength(...)
return(c(n1, n2, n3))
}
myfun(stop("A"), stop("B"), someArg = stop("c"))
I don't really see immediately how one can replace the C definition with
Hadley's solution without changing how the function has to be used.
Personally, I have no preference over the use, but changing it now would
break code dependent upon ...length() imho. Unless I'm overlooking
something of course.
Cheers
Joris
On Fri, May 4, 2018 at 3:02 PM, Martin Maechler <maechler at stat.math.ethz.ch>
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://stat.ethz.ch/mailman/listinfo/r-devel
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
--
Joris Meys
Statistical consultant
Department of Data Analysis and Mathematical Modelling
Ghent University
Coupure Links 653, B-9000 Gent (Belgium)
<https://maps.google.com/?q=Coupure+links+653,%C2%A0B-9000+Gent,%C2%A0Belgium&entry=gmail&source=g>
-----------
Biowiskundedagen 2017-2018
http://www.biowiskundedagen.ugent.be/
-------------------------------
Disclaimer : http://helpdesk.ugent.be/e-maildisclaimer.php
[[alternative HTML version deleted]]
More information about the R-devel
mailing list