[R] Extracting specific arguments from "..."

Ian Farm |@n@|@rm @end|ng |rom m@|ne@edu
Thu Jan 9 14:12:00 CET 2025


I might add that there seems to be a subtle difference between using
`...elt()` and `match.call()`, which is that the former causes `a` itself
to be evaluated while the latter doesn't:
```
# Some approaches that have been suggested:

# 1. Using `list()` (Bert Gunter)
f1 <- function(...) list(...)[["a"]]
# 2. Using `...elt()` (Bert Gunter)
f2 <- function(...) ...elt(match("a", ...names()))
# 3. Using argument matching (Hadley Wickham)
f3 <- function(...) (\(a, ...) a)(...)
# 4. Using `match.call()`
f4 <- function(...) eval(match.call()[["a"]], parent.frame())

ff <- list(f1 = f1, f2 = f2, f3 = f3, f4 = f4)

sapply(ff, \(f) {
  f(b = 2, a = 1, c = 3)
})
#> f1 f2 f3 f4
#>  1  1  1  1

# View the (defused) arguments after `a` has been accessed:

# returns an expression if the argument has not been evaluated, and a
number if it has
check_forced_args <- function(f) {
  body(f) <- call("{", body(f), quote(rlang::enexprs(...)))
  # pass `f()` some expressions to see which are evaluated
  f(a = cos(0), b = sqrt(4))
}
# make a data frame showing the defused arguments for each function
lapply(ff, check_forced_args) |> do.call(rbind, args = _) |> as.data.frame()

#>         a       b
#> f1      1       2    # all the arguments are forced
#> f2      1 sqrt(4)    # only `a` is forced
#> f3      1 sqrt(4)    # only `a` is forced
#> f4 cos(0) sqrt(4)    # none of the arguments are forced
```

Also, here's a possible way to adapt Hadley Wickham's approach so that it
takes the name of the argument as a string, though it does lose the
elegance:
```
pick_arg <- function(nm) {
  as.function(c(
    setNames(alist(. = , . = ), c(nm, "...")),
    as.symbol(nm)
  ))
}

z <- "a"
f5 <- function(...) {
  pick_arg(z)(...)
}
f5(b = 2, a = 1, c = 3)
#> [1] 1
```

Regards,
Ian
____
Ian Farm, Laboratory Manager
University of Maine Agroecology Lab


On Wed, Jan 8, 2025 at 5:58 PM Bert Gunter <bgunter.4567 using gmail.com> wrote:

> That's very nice, Hadley. Simple and clean. Never would have thought of it
> myself.
>
> As usual, however, in the course of my churnings, I have a further
> complication to add. But first ...
>
> **TO ALL**: Feel free to ignore the following, as I'm just fooling around
> here and don't want to waste your time with my stupid stuff.
>
> Anyway, the complication is motivated by the use of formals() or otherwise
> that *programmatically* generates a character representation of the
> arguments I want to select. So, for example:
>
> > z <- "a"
> ## Then:
> f1 <- function(...){
>     ...elt(match(z, ...names())) ## since z gets evaluated in the call
> }
> ## still works.
> > f1(b =2, a=1, c=3)
> [1] 1
>
> But I haven't figured out how to modify your suggestion -- at least in a
> simple way -- to do the same. Likely I've missed something, though.
>
>
> Cheers,
> Bert
>
>
>
>
>
>
> On Wed, Jan 8, 2025 at 12:51 PM Hadley Wickham <h.wickham using gmail.com>
> wrote:
>
> > I'd propose an alternative that I think is superior: rely on the
> semantics
> > of ... to do the work for you:
> >
> > f1 <- function(...){
> >   one <- list(...)[['a']]
> >   two <- ...elt(match('a', ...names()))
> >   c(one, two, three(...))
> > }
> >
> > three <- function(a, ...) {
> >   a
> > }
> >
> > f1(a = 1, b = 2, c = 3)
> > #> [1] 1 1 1
> >
> >
> > On Sun, Jan 5, 2025 at 12:00 PM Bert Gunter <bgunter.4567 using gmail.com>
> > wrote:
> >
> >> Consider:
> >>
> >> f1 <- function(...){
> >>   one <- list(...)[['a']]
> >>   two <- ...elt(match('a', ...names()))
> >>   c(one, two)
> >> }
> >> ## Here "..." is an argument list with "a" somewhere in it, but in an
> >> unknown position.
> >>
> >> > f1(b=5, a = 2, c=7)
> >> [1] 2 2
> >>
> >> Which is better for extracting a specific named argument, one<- or
> >> two<- ?  Or a third alternative that is better than both?
> >> Comments and critiques welcome.
> >>
> >> Cheers,
> >> Bert
> >>
> >> ______________________________________________
> >> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> >> https://stat.ethz.ch/mailman/listinfo/r-help
> >> PLEASE do read the posting guide
> >> https://www.R-project.org/posting-guide.html
> >> and provide commented, minimal, self-contained, reproducible code.
> >>
> >
> >
> > --
> > http://hadley.nz
> >
>
>         [[alternative HTML version deleted]]
>
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
> https://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>

	[[alternative HTML version deleted]]



More information about the R-help mailing list