Thanks Martin for the clarifications.  H.

On 05/04/2018 06:02 AM, Martin Maechler wrote:
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://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: 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

Reply via email to