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

2025-01-09 Thread Bert Gunter
Thanks Ian (and others),

Taking the advice of ?"..." (which I should have done at the outset ...
duhh!),  the following seems to be the simplest solution, adequate for my
needs at least:

f <- function(x, ...){
   lapply(seq_along(x), \(i)switch(x[i], ..., NA))
}

(the usual argument checking etc. should be added, of course.)

Comparing this to the ...xx() functions that I previously gave, which are
the same as names(list(...)) etc. without the overhead of unnecessary
evaluation, gives:

g <- function(...){
   one <- f(z,...)
   two <- lapply(charmatch(z, ...names()), \(i)...elt(i))
  list(one = one, two = two)
}

> k <- 5
> z <- c("a","c")
> g(b=2, a=1, c = k)
$one
$one[[1]]
[1] 1

$one[[2]]
[1] 5


$two
$two[[1]]
[1] 1

$two[[2]]
[1] 5

As always, corrections and comments welcomed.

Cheers,
Bert



On Thu, Jan 9, 2025 at 5:12 AM Ian Farm  wrote:

> 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  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 
>> 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 
>> > 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
>> >>
>> >> __
>> >> [email protected] mailing list -- To UNSUBSCRIBE and more, see
>> >> https://stat.ethz.ch/ma

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

2025-01-09 Thread Ian Farm
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  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 
> 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 
> > 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
> >>
> >> __
> >> [email protected] 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]]
>
> __
> [email protected] 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]]

__
[email protected] 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.


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

2025-01-08 Thread Bert Gunter
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  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 
> 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
>>
>> __
>> [email protected] 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]]

__
[email protected] 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.


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

2025-01-08 Thread Hadley Wickham
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  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
>
> __
> [email protected] 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]]

__
[email protected] 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.


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

2025-01-08 Thread Martin Maechler
> Sorkin, John 
> on Tue, 7 Jan 2025 22:03:02 + writes:

> Colleagues,
> My interest is not in writing ad hoc functions (which I might use once to 
analyze my data), but rather what I will call a system function that might be 
part of a package. The lm function is a paradigm of what I call a system 
function. 

> The lm function begins by processing the arguments passed to the function 
(represented in the function as parameters, see code below.) Much of this 
processing is only peripherally related to running a regression, but the code 
is necessary to determine exactly what the user of the system function wants 
the function to do. It would be helpful if there was a document that would 
describe best practices when writing system functions, with clear explanations 
of what each step in system function is designed to do and how the line 
accomplishes its task. It would also be nice if the system function had 
documentation. I have pushed my way through the lm function, and with the help 
of R help files, I have come to understand how the function works, but this is 
not an efficient way to learn best practices that should be used when writing a 
system function. 

> Perhaps there is a document that does what I would like to see done, but 
I do not know of one.  

> John

Note that the following is *not* the source of the lm() function, but a
print out to your console of what has become from the original source.
Notably all comments *and* all original author formatting has
been lost (as the "system functions" are *not* installed with
   something like options(keep.source = TRUE)).

For a long time, many have strongly advised to use the source
(e.g. https://en.wiktionary.org/wiki/UTSL   "Use The Source, Luke!")
instead. Here's the always latest (development / R-devel) source
for lm() *and* related functions ... also with comments etc:
  --> https://svn.r-project.org/R/trunk/src/library/stats/R/lm.R

(or you use one of its github mirrors ..)

Martin


> lm

> function (formula, data, subset, weights, na.action, method = "qr",
> model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
> contrasts = NULL, offset, ...)
> {
> ret.x <- x
> ret.y <- y
> cl <- match.call()
> mf <- match.call(expand.dots = FALSE)
> m <- match(c("formula", "data", "subset", "weights", "na.action",
> "offset"), names(mf), 0L)
> mf <- mf[c(1L, m)]
> mf$drop.unused.levels <- TRUE
> mf[[1L]] <- quote(stats::model.frame)
> mf <- eval(mf, parent.frame())
> if (method == "model.frame")
> return(mf)
> else if (method != "qr")
> warning(gettextf("method = '%s' is not supported. Using 'qr'",
> method), domain = NA)
> mt <- attr(mf, "terms")
> y <- model.response(mf, "numeric")
> w <- as.vector(model.weights(mf))
> if (!is.null(w) && !is.numeric(w))
> stop("'weights' must be a numeric vector")
> offset <- model.offset(mf)
> mlm <- is.matrix(y)
> ny <- if (mlm)
> nrow(y)
> else length(y)
> if (!is.null(offset)) {
> if (!mlm)
> offset <- as.vector(offset)
> if (NROW(offset) != ny)
> stop(gettextf("number of offsets is %d, should equal %d (number of 
observations)",
> NROW(offset), ny), domain = NA)
> }
> if (is.empty.model(mt)) {
> x <- NULL
> z <- list(coefficients = if (mlm) matrix(NA_real_, 0,
> ncol(y)) else numeric(), residuals = y, fitted.values = 0 *
> y, weights = w, rank = 0L, df.residual = if (!is.null(w)) sum(w !=
> 0) else ny)
> if (!is.null(offset)) {
> z$fitted.values <- offset
> z$residuals <- y - offset
> }
> }
> else {
> x <- model.matrix(mt, mf, contrasts)
> z <- if (is.null(w))
> lm.fit(x, y, offset = offset, singular.ok = singular.ok,
> ...)
> else lm.wfit(x, y, w, offset = offset, singular.ok = singular.ok,
> ...)
> }
> class(z) <- c(if (mlm) "mlm", "lm")
> z$na.action <- attr(mf, "na.action")
> z$offset <- offset
> z$contrasts <- attr(x, "contrasts")
> z$xlevels <- .getXlevels(mt, mf)
> z$call <- cl
> z$terms <- mt
> if (model)
> z$model <- mf
> if (ret.x)
> z$x <- x
> if (ret.y)
> z$y <- y
> if (!qr)
> z$qr <- NULL
> z
> }



> John David Sorkin M.D., Ph.D.
> Professor of Medicine, University of Maryland School of Medicine;
> Associate Director for Biostatistics and Informatics, Baltimore VA 
Medical Center Geriatrics Research, Education, and Clinical Center; 
> PI Biostatistics and Informatics Core, University of Maryland School of 
Medicine Claude D. Pepper Older Americans Independence Center;
> Senior Statistician University of Maryland Center for Vascular Research;

> Division of Gerontology and Paliative Care,
> 10 North Greene Street
> GRECC (BT/18/GR)
> Baltimore, MD 21201-1524
> Cell phone 443-418-5382




> _

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

2025-01-07 Thread avi.e.gross
Like many things in R, the original way things were done may have ossified
in place and even if largely unknown packages came along, may not be known
by many.

The topic John is talking about is NOT in my mind about systems programming
at all. It is about writing any function where you want control over
evaluating arguments. There may be a better way from a programmers
perspective.

I can imagine a set of functions in a package that are well designed and
hide all the details so they can be easily used. I suspect aspects of what I
am talking about have been done. They could include some "logical" functions
that test if an option has been specified, or even if it is just the
default, without evaluating anything. Other functions would return a
specified argument. Yet others would remove a specified argument so further
evaluation does not see it, including removing it from ... so that in the
end, you can pass along a reduced ... to other functions you call.

I understand some R evaluations can be tricky or even have side effects. But
something better than what I have seen seems quite possible.

Other languages have variants such as getopt() that are a tad different but
quite useful.

-Original Message-
From: R-help  On Behalf Of Sorkin, John
Sent: Tuesday, January 7, 2025 6:54 PM
To: Ben Bolker ; [email protected]
Subject: Re: [R] Extracting specific arguments from "..."

Ben,
As always, thank you.
You are correct, it is something like what I want, but not exactly. Perhaps
someday someone will write a more complete guide.
Thank you,
John


John David Sorkin M.D., Ph.D.
Professor of Medicine, University of Maryland School of Medicine;
Associate Director for Biostatistics and Informatics, Baltimore VA Medical
Center Geriatrics Research, Education, and Clinical Center;
PI Biostatistics and Informatics Core, University of Maryland School of
Medicine Claude D. Pepper Older Americans Independence Center;
Senior Statistician University of Maryland Center for Vascular Research;

Division of Gerontology and Paliative Care,
10 North Greene Street
GRECC (BT/18/GR)
Baltimore, MD 21201-1524
Cell phone 443-418-5382





From: R-help  on behalf of Ben Bolker

Sent: Tuesday, January 7, 2025 5:06 PM
To: [email protected]
Subject: Re: [R] Extracting specific arguments from "..."


   There's an ancient (2003) document on the CRAN "developers' page"
https://developer.r-project.org/model-fitting-functions.html that is
sort of (but not exactly) what you're looking for ...


On 2025-01-07 5:03 p.m., Sorkin, John wrote:
> Colleagues,
>
> My interest is not in writing ad hoc functions (which I might use once to
analyze my data), but rather what I will call a system function that might
be part of a package. The lm function is a paradigm of what I call a system
function.
>
> The lm function begins by processing the arguments passed to the function
(represented in the function as parameters, see code below.) Much of this
processing is only peripherally related to running a regression, but the
code is necessary to determine exactly what the user of the system function
wants the function to do. It would be helpful if there was a document that
would describe best practices when writing system functions, with clear
explanations of what each step in system function is designed to do and how
the line accomplishes its task. It would also be nice if the system function
had documentation. I have pushed my way through the lm function, and with
the help of R help files, I have come to understand how the function works,
but this is not an efficient way to learn best practices that should be used
when writing a system function.
>
> Perhaps there is a document that does what I would like to see done, but I
do not know of one.
>
> John
>
> lmlm
> function (formula, data, subset, weights, na.action, method = "qr",
>  model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
>  contrasts = NULL, offset, ...)
> {
>  ret.x <- x
>  ret.y <- y
>  cl <- match.call()
>  mf <- match.call(expand.dots = FALSE)
>  m <- match(c("formula", "data", "subset", "weights", "na.action",
>  "offset"), names(mf), 0L)
>  mf <- mf[c(1L, m)]
>  mf$drop.unused.levels <- TRUE
>  mf[[1L]] <- quote(stats::model.frame)
>  mf <- eval(mf, parent.frame())
>  if (method == "model.frame")
>  return(mf)
>  else if (method != "qr")
>  warning(gettextf("method = '%s' is not supported. Using 'qr'",
>  method), domain = NA)
>  mt <- attr(mf, "terms")
>  y <- model.response(mf, "numeric")
>  w <- as.ve

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

2025-01-07 Thread Sorkin, John
Ben,
As always, thank you.
You are correct, it is something like what I want, but not exactly. Perhaps 
someday someone will write a more complete guide.
Thank you,
John


John David Sorkin M.D., Ph.D.
Professor of Medicine, University of Maryland School of Medicine;
Associate Director for Biostatistics and Informatics, Baltimore VA Medical 
Center Geriatrics Research, Education, and Clinical Center;
PI Biostatistics and Informatics Core, University of Maryland School of 
Medicine Claude D. Pepper Older Americans Independence Center;
Senior Statistician University of Maryland Center for Vascular Research;

Division of Gerontology and Paliative Care,
10 North Greene Street
GRECC (BT/18/GR)
Baltimore, MD 21201-1524
Cell phone 443-418-5382





From: R-help  on behalf of Ben Bolker 

Sent: Tuesday, January 7, 2025 5:06 PM
To: [email protected]
Subject: Re: [R] Extracting specific arguments from "..."


   There's an ancient (2003) document on the CRAN "developers' page"
https://developer.r-project.org/model-fitting-functions.html that is
sort of (but not exactly) what you're looking for ...


On 2025-01-07 5:03 p.m., Sorkin, John wrote:
> Colleagues,
>
> My interest is not in writing ad hoc functions (which I might use once to 
> analyze my data), but rather what I will call a system function that might be 
> part of a package. The lm function is a paradigm of what I call a system 
> function.
>
> The lm function begins by processing the arguments passed to the function 
> (represented in the function as parameters, see code below.) Much of this 
> processing is only peripherally related to running a regression, but the code 
> is necessary to determine exactly what the user of the system function wants 
> the function to do. It would be helpful if there was a document that would 
> describe best practices when writing system functions, with clear 
> explanations of what each step in system function is designed to do and how 
> the line accomplishes its task. It would also be nice if the system function 
> had documentation. I have pushed my way through the lm function, and with the 
> help of R help files, I have come to understand how the function works, but 
> this is not an efficient way to learn best practices that should be used when 
> writing a system function.
>
> Perhaps there is a document that does what I would like to see done, but I do 
> not know of one.
>
> John
>
> lmlm
> function (formula, data, subset, weights, na.action, method = "qr",
>  model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
>  contrasts = NULL, offset, ...)
> {
>  ret.x <- x
>  ret.y <- y
>  cl <- match.call()
>  mf <- match.call(expand.dots = FALSE)
>  m <- match(c("formula", "data", "subset", "weights", "na.action",
>  "offset"), names(mf), 0L)
>  mf <- mf[c(1L, m)]
>  mf$drop.unused.levels <- TRUE
>  mf[[1L]] <- quote(stats::model.frame)
>  mf <- eval(mf, parent.frame())
>  if (method == "model.frame")
>  return(mf)
>  else if (method != "qr")
>  warning(gettextf("method = '%s' is not supported. Using 'qr'",
>  method), domain = NA)
>  mt <- attr(mf, "terms")
>  y <- model.response(mf, "numeric")
>  w <- as.vector(model.weights(mf))
>  if (!is.null(w) && !is.numeric(w))
>  stop("'weights' must be a numeric vector")
>  offset <- model.offset(mf)
>  mlm <- is.matrix(y)
>  ny <- if (mlm)
>  nrow(y)
>  else length(y)
>  if (!is.null(offset)) {
>  if (!mlm)
>  offset <- as.vector(offset)
>  if (NROW(offset) != ny)
>  stop(gettextf("number of offsets is %d, should equal %d (number 
> of observations)",
>  NROW(offset), ny), domain = NA)
>  }
>  if (is.empty.model(mt)) {
>  x <- NULL
>  z <- list(coefficients = if (mlm) matrix(NA_real_, 0,
>  ncol(y)) else numeric(), residuals = y, fitted.values = 0 *
>  y, weights = w, rank = 0L, df.residual = if (!is.null(w)) sum(w 
> !=
>  0) else ny)
>  if (!is.null(offset)) {
>  z$fitted.values <- offset
>  z$residuals <- y - offset
>  }
>  }
>  else {
>  x <- model.matrix(mt, mf, contrasts)
>  z <- if (is.null(w))
>  lm.fit(x, y, offset = offset, singular.ok = singular.ok,
>  

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

2025-01-07 Thread Ben Bolker



  There's an ancient (2003) document on the CRAN "developers' page" 
https://developer.r-project.org/model-fitting-functions.html that is 
sort of (but not exactly) what you're looking for ...



On 2025-01-07 5:03 p.m., Sorkin, John wrote:

Colleagues,

My interest is not in writing ad hoc functions (which I might use once to 
analyze my data), but rather what I will call a system function that might be 
part of a package. The lm function is a paradigm of what I call a system 
function.

The lm function begins by processing the arguments passed to the function 
(represented in the function as parameters, see code below.) Much of this 
processing is only peripherally related to running a regression, but the code 
is necessary to determine exactly what the user of the system function wants 
the function to do. It would be helpful if there was a document that would 
describe best practices when writing system functions, with clear explanations 
of what each step in system function is designed to do and how the line 
accomplishes its task. It would also be nice if the system function had 
documentation. I have pushed my way through the lm function, and with the help 
of R help files, I have come to understand how the function works, but this is 
not an efficient way to learn best practices that should be used when writing a 
system function.

Perhaps there is a document that does what I would like to see done, but I do 
not know of one.

John

lmlm
function (formula, data, subset, weights, na.action, method = "qr",
 model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
 contrasts = NULL, offset, ...)
{
 ret.x <- x
 ret.y <- y
 cl <- match.call()
 mf <- match.call(expand.dots = FALSE)
 m <- match(c("formula", "data", "subset", "weights", "na.action",
 "offset"), names(mf), 0L)
 mf <- mf[c(1L, m)]
 mf$drop.unused.levels <- TRUE
 mf[[1L]] <- quote(stats::model.frame)
 mf <- eval(mf, parent.frame())
 if (method == "model.frame")
 return(mf)
 else if (method != "qr")
 warning(gettextf("method = '%s' is not supported. Using 'qr'",
 method), domain = NA)
 mt <- attr(mf, "terms")
 y <- model.response(mf, "numeric")
 w <- as.vector(model.weights(mf))
 if (!is.null(w) && !is.numeric(w))
 stop("'weights' must be a numeric vector")
 offset <- model.offset(mf)
 mlm <- is.matrix(y)
 ny <- if (mlm)
 nrow(y)
 else length(y)
 if (!is.null(offset)) {
 if (!mlm)
 offset <- as.vector(offset)
 if (NROW(offset) != ny)
 stop(gettextf("number of offsets is %d, should equal %d (number of 
observations)",
 NROW(offset), ny), domain = NA)
 }
 if (is.empty.model(mt)) {
 x <- NULL
 z <- list(coefficients = if (mlm) matrix(NA_real_, 0,
 ncol(y)) else numeric(), residuals = y, fitted.values = 0 *
 y, weights = w, rank = 0L, df.residual = if (!is.null(w)) sum(w !=
 0) else ny)
 if (!is.null(offset)) {
 z$fitted.values <- offset
 z$residuals <- y - offset
 }
 }
 else {
 x <- model.matrix(mt, mf, contrasts)
 z <- if (is.null(w))
 lm.fit(x, y, offset = offset, singular.ok = singular.ok,
 ...)
 else lm.wfit(x, y, w, offset = offset, singular.ok = singular.ok,
 ...)
 }
 class(z) <- c(if (mlm) "mlm", "lm")
 z$na.action <- attr(mf, "na.action")
 z$offset <- offset
 z$contrasts <- attr(x, "contrasts")
 z$xlevels <- .getXlevels(mt, mf)
 z$call <- cl
 z$terms <- mt
 if (model)
 z$model <- mf
 if (ret.x)
 z$x <- x
 if (ret.y)
 z$y <- y
 if (!qr)
 z$qr <- NULL
 z
}



John David Sorkin M.D., Ph.D.
Professor of Medicine, University of Maryland School of Medicine;
Associate Director for Biostatistics and Informatics, Baltimore VA Medical 
Center Geriatrics Research, Education, and Clinical Center;
PI Biostatistics and Informatics Core, University of Maryland School of 
Medicine Claude D. Pepper Older Americans Independence Center;
Senior Statistician University of Maryland Center for Vascular Research;

Division of Gerontology and Paliative Care,
10 North Greene Street
GRECC (BT/18/GR)
Baltimore, MD 21201-1524
Cell phone 443-418-5382





From: Jorgen Harmse 
Sent: Tuesday, January 7, 2025 1:47 PM
To: [email protected]; [email protected]; Bert Gunter; Sorkin, John; 
[email protected]
Subject: Re: Extracting specific arguments from "..."

Interesting discussion. A few things occurred to me.

Apologies to Iris Simmons: I mixed up his answer with Bert's question.

Bert raises questions about promises, and I think they are related to John Sorkin's 
question. A big difference between R and most other languages is that function 
arguments are computed

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

2025-01-07 Thread Sorkin, John
Colleagues,

My interest is not in writing ad hoc functions (which I might use once to 
analyze my data), but rather what I will call a system function that might be 
part of a package. The lm function is a paradigm of what I call a system 
function. 

The lm function begins by processing the arguments passed to the function 
(represented in the function as parameters, see code below.) Much of this 
processing is only peripherally related to running a regression, but the code 
is necessary to determine exactly what the user of the system function wants 
the function to do. It would be helpful if there was a document that would 
describe best practices when writing system functions, with clear explanations 
of what each step in system function is designed to do and how the line 
accomplishes its task. It would also be nice if the system function had 
documentation. I have pushed my way through the lm function, and with the help 
of R help files, I have come to understand how the function works, but this is 
not an efficient way to learn best practices that should be used when writing a 
system function. 

Perhaps there is a document that does what I would like to see done, but I do 
not know of one.  

John

lmlm
function (formula, data, subset, weights, na.action, method = "qr",
model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
contrasts = NULL, offset, ...)
{
ret.x <- x
ret.y <- y
cl <- match.call()
mf <- match.call(expand.dots = FALSE)
m <- match(c("formula", "data", "subset", "weights", "na.action",
"offset"), names(mf), 0L)
mf <- mf[c(1L, m)]
mf$drop.unused.levels <- TRUE
mf[[1L]] <- quote(stats::model.frame)
mf <- eval(mf, parent.frame())
if (method == "model.frame")
return(mf)
else if (method != "qr")
warning(gettextf("method = '%s' is not supported. Using 'qr'",
method), domain = NA)
mt <- attr(mf, "terms")
y <- model.response(mf, "numeric")
w <- as.vector(model.weights(mf))
if (!is.null(w) && !is.numeric(w))
stop("'weights' must be a numeric vector")
offset <- model.offset(mf)
mlm <- is.matrix(y)
ny <- if (mlm)
nrow(y)
else length(y)
if (!is.null(offset)) {
if (!mlm)
offset <- as.vector(offset)
if (NROW(offset) != ny)
stop(gettextf("number of offsets is %d, should equal %d (number of 
observations)",
NROW(offset), ny), domain = NA)
}
if (is.empty.model(mt)) {
x <- NULL
z <- list(coefficients = if (mlm) matrix(NA_real_, 0,
ncol(y)) else numeric(), residuals = y, fitted.values = 0 *
y, weights = w, rank = 0L, df.residual = if (!is.null(w)) sum(w !=
0) else ny)
if (!is.null(offset)) {
z$fitted.values <- offset
z$residuals <- y - offset
}
}
else {
x <- model.matrix(mt, mf, contrasts)
z <- if (is.null(w))
lm.fit(x, y, offset = offset, singular.ok = singular.ok,
...)
else lm.wfit(x, y, w, offset = offset, singular.ok = singular.ok,
...)
}
class(z) <- c(if (mlm) "mlm", "lm")
z$na.action <- attr(mf, "na.action")
z$offset <- offset
z$contrasts <- attr(x, "contrasts")
z$xlevels <- .getXlevels(mt, mf)
z$call <- cl
z$terms <- mt
if (model)
z$model <- mf
if (ret.x)
z$x <- x
if (ret.y)
z$y <- y
if (!qr)
z$qr <- NULL
z
}



John David Sorkin M.D., Ph.D.
Professor of Medicine, University of Maryland School of Medicine;
Associate Director for Biostatistics and Informatics, Baltimore VA Medical 
Center Geriatrics Research, Education, and Clinical Center; 
PI Biostatistics and Informatics Core, University of Maryland School of 
Medicine Claude D. Pepper Older Americans Independence Center;
Senior Statistician University of Maryland Center for Vascular Research;

Division of Gerontology and Paliative Care,
10 North Greene Street
GRECC (BT/18/GR)
Baltimore, MD 21201-1524
Cell phone 443-418-5382





From: Jorgen Harmse 
Sent: Tuesday, January 7, 2025 1:47 PM
To: [email protected]; [email protected]; Bert Gunter; Sorkin, John; 
[email protected]
Subject: Re: Extracting specific arguments from "..."

Interesting discussion. A few things occurred to me.

Apologies to Iris Simmons: I mixed up his answer with Bert's question.

Bert raises questions about promises, and I think they are related to John 
Sorkin's question. A big difference between R and most other languages is that 
function arguments are computed lazily. match.call & substitute tell us what 
expressions will be evaluated if function arguments are needed but not the 
environments in which that will happen. The usual suspects are environment() 
and parent.frame(), but parent.frame(k) & maybe even other environments are 
possible. If you are really det

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

2025-01-07 Thread Jorgen Harmse via R-help
Interesting discussion. A few things occurred to me.

Apologies to Iris Simmons: I mixed up his answer with Bert's question.

Bert raises questions about promises, and I think they are related to John 
Sorkin's question. A big difference between R and most other languages is that 
function arguments are computed lazily. match.call & substitute tell us what 
expressions will be evaluated if function arguments are needed but not the 
environments in which that will happen. The usual suspects are environment() 
and parent.frame(), but parent.frame(k) & maybe even other environments are 
possible. If you are really determined then I guess you can keep evaluating 
match.call() in parent frames until you have accounted for all the inputs.

It's not clear to what extent John Sorkin is concerned about writing functions 
as opposed to using functions. Lazy computation has advantages but leads to 
some issues.
Exactly matching the function's default expression for an input is not 
necessarily the same as omitting the input. The evaluation environment is 
different.
If the caller uses an expression with side effects then there is no guarantee 
that the side effects will happen. If there are side effects from two or more 
inputs then the order is uncertain. (If an argument is not supplied and the 
default has side effects then they might not happen either. However, I don't 
know why the function writer would specify any side effect except stop(), and 
then he or she has probably arranged for it to happen exactly when it should.)
If a default value depends on another input and that input is modified inside 
the function then order of evaluation of inputs becomes important. Even if you 
know exactly what you're doing when you write the function, you should make it 
clear to future maintainers. An explicit call to force clarifies that the input 
needs to be computed with the existing values of anything that is used in the 
default, even if the code is refactored so that the value is not used 
immediately. If you really want to modify another input before evaluating the 
default then specify that in a comment.

Jeff Newmiller makes a good point. You can still change your mind about 
inspecting a particular input without breaking old code that uses your 
function, and you don�t necessarily need default values.

Old definition: f <- function(�) {}

New definition:
f <- function(�, a = )
{ 
  
}

OR

f <- function(�, a)
{ if (missing(a)) # OK, this becomes clunky if there are several such inputs
  { < pass � to another function >}
  else
 {  # Pitfall: Changing the order of evaluation may break 
old code, but then the design was probably too devious in the first place.

  }
  
}

Regards,
Jorgen Harmse.




[[alternative HTML version deleted]]

__
[email protected] 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.


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

2025-01-06 Thread Jeff Newmiller via R-help
iversity of Maryland School of
>> Medicine Claude D. Pepper Older Americans Independence Center;
>> >Senior Statistician University of Maryland Center for Vascular Research;
>> >
>> >Division of Gerontology and Paliative Care,
>> >10 North Greene Street
>> >GRECC (BT/18/GR)
>> >Baltimore, MD 21201-1524
>> >Cell phone 443-418-5382
>> >
>> >
>> >
>> >
>> >
>> >From: R-help  on behalf of Bert Gunter <
>> [email protected]>
>> >Sent: Monday, January 6, 2025 5:22 PM
>> >To: Jorgen Harmse
>> >Cc: [email protected]
>> >Subject: Re: [R] Extracting specific arguments from "..."
>> >
>> >Thanks Jorgen.
>> >
>> >I thought your approach to getting the argument expressions was clever,
>> but
>> >somewhat convoluted. I think the usual simple way is to use match.call()
>> >(or sys.call() )to get the unevaluated argument expressions;  e.g. ...
>> >
>> >f <- function(...){
>> >   match.call()
>> >}
>> >> f(a = 'red', b = sin(zzz))
>> >f(a = "red", b = sin(zzz))
>> >
>> >The return value is an object of class call that can be subscripted as (or
>> >converted by as.list() to) a list to extract the argument expressions:
>> >> f(a = 'red', b = sin(zzz))$b
>> >sin(zzz)
>> >
>> >You'll note that the $b component is again of class "call". So you may
>> wish
>> >to convert it to character or expression or whatever for further
>> >processing, depending on context. Obviously, I haven't thought about this
>> >carefully.
>> >
>> >You raise an important point about robustness. I believe this approach to
>> >extracting the call expressions should be fairly robust, but I do get
>> >confused about the lay of the land when you add promises with default
>> >arguments that may not yet have been forced before match.call() is called.
>> >You may have to wrestle with sys.call() and it's "wh" argument to make
>> >things work the way you want in that situation. I leave such delights to
>> >wiser heads, as well as any corrections or refinements to anything that
>> >I've said here.
>> >
>> >Cheers,
>> >Bert
>> >
>> >On Mon, Jan 6, 2025 at 9:55 AM Jorgen Harmse  wrote:
>> >
>> >> I think Bert Gunter is right, but do you want partial matches (not found
>> >> by match), and how robust do you want the code to be?
>> >>
>> >>
>> >>
>> >> f <- function(…)
>> >>
>> >> { pos <- match('a', ...names())
>> >>
>> >>   if (is.na(pos))
>> >>
>> >> stop("a is required.")
>> >>
>> >>   …elt(pos)
>> >>
>> >> }
>> >>
>> >>
>> >>
>> >> Incidentally, what is the best way to extract the expression without
>> >> evaluating it?
>> >>
>> >>
>> >>
>> >> g <- function(...)
>> >>
>> >> { pos <- match('a',...names())
>> >>
>> >>   if (is.na(pos))
>> >>
>> >> stop("a is missing.")
>> >>
>> >>   (function(a,...) substitute(a)) (...)
>> >>
>> >> }
>> >>
>> >>
>> >>
>> >> Regards,
>> >>
>> >> Jorgen Harmse.
>> >>
>> >>
>> >>
>> >> Message: 8
>> >> Date: Sun, 5 Jan 2025 11:17:02 -0800
>> >> From: Bert Gunter 
>> >> To: Iris Simmons 
>> >> Cc: R-help 
>> >> Subject: Re: [R] Extracting specific arguments from "..."
>> >> Message-ID:
>> >> <
>> >> cagxfjbronopt-bodf6srpp79bwucppoo3+ycdgn3y-ytdu5...@mail.gmail.com>
>> >> Content-Type: text/plain; charset="utf-8"
>> >>
>> >> Thanks, Iris.
>> >> That is what I suspected, but it wasn't clear to me from the docs.
>> >>
>> >> Best,
>> >> Bert
>> >>
>> >> On Sun, Jan 5, 2025 at 10:16 AM Iris Simmons 
>> wrote:
>> >> >
>> >> > I would use two because it does not force the evaluation of the other
>> >> arguments in the ... list.
>

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

2025-01-06 Thread Bert Gunter
Jeff:
Would you care to offer an example of:

"String literals are surprisingly simple alternatives that don't bite you
in the butt nearly so often as NSE does."

"No" is a perfectly acceptable answer.

I would generally agree with you about NSE, but my original query was
motivated by something simple. I like to use lattice graphics when I fool
around with graphing data, as I'm retired and don't have to worry about
adhering to organizational or journal standards built around the ggplot
graphics grammar or require it's very extensive and sophisticated
capabilities. But I do often create custom panel displays, which typically
requires that I have to pass around long default lists of graphics
arguments via "..." that I modify to suit my aesthetic and analytical
preferences. Ergo my query about how to check what's in the "..." list
without requiring evaluation, which Iris helped me with.

I would also suggest that as a personal user of R for "data science stuff",
one can avoid a lot of the complexities to which you allude; while as a
developer of "tools" (chiefly packages) for others, one has to wade into a
lot of those complexities. This is just a software cliché I think.
Unfortunately, S and therefore R, were originally designed for a pretty
sophisticated audience (ATT labs researchers) and intentionally, and to me
rather seductively, blurred the line between "user" and "developer."  All
IMO, of course. YMMV.

Cheers,
Bert


On Mon, Jan 6, 2025 at 4:04 PM Jeff Newmiller 
wrote:

> It is a pretty tricky topic, but IMO Advanced R [1] steps you through it
> systematically... you just have to be prepared to follow along in R with
> the examples as you read it. In particular, the chapter on Functions goes
> through this.
>
> The subtleties of how base R gives you control over these topics is what
> lead to the tidyverse creating new packages to build such function
> interfaces. Manipulating object evaluation from arbitrary environments is
> still complex, and the more you learn about it the more you learn to avoid
> it for certain types of tasks. String literals are surprisingly simple
> alternatives that don't bite you in the butt nearly so often as NSE does.
>
> [1] https://adv-r.hadley.nz/
>
> On January 6, 2025 3:26:25 PM PST, "Sorkin, John" <
> [email protected]> wrote:
> >Bert and other on this Chain,
> >
> >The original question asked by Bert Gunter, highlights one of my long
> standing wishes. Perhaps my wish has already been fulfilled (if it has,
> please let me know where I can look of fulfill my wish), if it hasn't
> perhaps someone can grant me my wish.
> >
> >I have tried to understand how to write a function (beyond a basic
> function), get values of the parameters, and process the parameters. I have
> looked for a source that clearly describes how his may be done (with
> examples), but I have yet to find one. Yes, one can look at a function
> (e.g. lm) look at the statements that are used and use the help system to
> research each of the statements (I have done this), but doing this is not
> the most efficient way to learn the topic. It would be very helpful if
> someone Knowledgeable would put together a primer on writing functions and
> processing function arguments. If such a document exist, I would be happy
> to have someone send me its URL.
> >
> >Thank you,
> >John
> >
> >John David Sorkin M.D., Ph.D.
> >Professor of Medicine, University of Maryland School of Medicine;
> >Associate Director for Biostatistics and Informatics, Baltimore VA
> Medical Center Geriatrics Research, Education, and Clinical Center;
> >PI Biostatistics and Informatics Core, University of Maryland School of
> Medicine Claude D. Pepper Older Americans Independence Center;
> >Senior Statistician University of Maryland Center for Vascular Research;
> >
> >Division of Gerontology and Paliative Care,
> >10 North Greene Street
> >GRECC (BT/18/GR)
> >Baltimore, MD 21201-1524
> >Cell phone 443-418-5382
> >
> >
> >
> >
> >
> >From: R-help  on behalf of Bert Gunter <
> [email protected]>
> >Sent: Monday, January 6, 2025 5:22 PM
> >To: Jorgen Harmse
> >Cc: [email protected]
> >Subject: Re: [R] Extracting specific arguments from "..."
> >
> >Thanks Jorgen.
> >
> >I thought your approach to getting the argument expressions was clever,
> but
> >somewhat convoluted. I think the usual simple way is to use match.call()
> >(or sys.call() )to get the unevaluated argument expressions;  e.g. ...
> >
> >f <- function(

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

2025-01-06 Thread Jeff Newmiller via R-help
It is a pretty tricky topic, but IMO Advanced R [1] steps you through it 
systematically... you just have to be prepared to follow along in R with the 
examples as you read it. In particular, the chapter on Functions goes through 
this.

The subtleties of how base R gives you control over these topics is what lead 
to the tidyverse creating new packages to build such function interfaces. 
Manipulating object evaluation from arbitrary environments is still complex, 
and the more you learn about it the more you learn to avoid it for certain 
types of tasks. String literals are surprisingly simple alternatives that don't 
bite you in the butt nearly so often as NSE does.

[1] https://adv-r.hadley.nz/

On January 6, 2025 3:26:25 PM PST, "Sorkin, John"  
wrote:
>Bert and other on this Chain,
>
>The original question asked by Bert Gunter, highlights one of my long standing 
>wishes. Perhaps my wish has already been fulfilled (if it has, please let me 
>know where I can look of fulfill my wish), if it hasn't perhaps someone can 
>grant me my wish.
>
>I have tried to understand how to write a function (beyond a basic function), 
>get values of the parameters, and process the parameters. I have looked for a 
>source that clearly describes how his may be done (with examples), but I have 
>yet to find one. Yes, one can look at a function (e.g. lm) look at the 
>statements that are used and use the help system to research each of the 
>statements (I have done this), but doing this is not the most efficient way to 
>learn the topic. It would be very helpful if someone Knowledgeable would put 
>together a primer on writing functions and processing function arguments. If 
>such a document exist, I would be happy to have someone send me its URL.
>
>Thank you,
>John
>
>John David Sorkin M.D., Ph.D.
>Professor of Medicine, University of Maryland School of Medicine;
>Associate Director for Biostatistics and Informatics, Baltimore VA Medical 
>Center Geriatrics Research, Education, and Clinical Center;
>PI Biostatistics and Informatics Core, University of Maryland School of 
>Medicine Claude D. Pepper Older Americans Independence Center;
>Senior Statistician University of Maryland Center for Vascular Research;
>
>Division of Gerontology and Paliative Care,
>10 North Greene Street
>GRECC (BT/18/GR)
>Baltimore, MD 21201-1524
>Cell phone 443-418-5382
>
>
>
>
>
>From: R-help  on behalf of Bert Gunter 
>
>Sent: Monday, January 6, 2025 5:22 PM
>To: Jorgen Harmse
>Cc: [email protected]
>Subject: Re: [R] Extracting specific arguments from "..."
>
>Thanks Jorgen.
>
>I thought your approach to getting the argument expressions was clever, but
>somewhat convoluted. I think the usual simple way is to use match.call()
>(or sys.call() )to get the unevaluated argument expressions;  e.g. ...
>
>f <- function(...){
>   match.call()
>}
>> f(a = 'red', b = sin(zzz))
>f(a = "red", b = sin(zzz))
>
>The return value is an object of class call that can be subscripted as (or
>converted by as.list() to) a list to extract the argument expressions:
>> f(a = 'red', b = sin(zzz))$b
>sin(zzz)
>
>You'll note that the $b component is again of class "call". So you may wish
>to convert it to character or expression or whatever for further
>processing, depending on context. Obviously, I haven't thought about this
>carefully.
>
>You raise an important point about robustness. I believe this approach to
>extracting the call expressions should be fairly robust, but I do get
>confused about the lay of the land when you add promises with default
>arguments that may not yet have been forced before match.call() is called.
>You may have to wrestle with sys.call() and it's "wh" argument to make
>things work the way you want in that situation. I leave such delights to
>wiser heads, as well as any corrections or refinements to anything that
>I've said here.
>
>Cheers,
>Bert
>
>On Mon, Jan 6, 2025 at 9:55 AM Jorgen Harmse  wrote:
>
>> I think Bert Gunter is right, but do you want partial matches (not found
>> by match), and how robust do you want the code to be?
>>
>>
>>
>> f <- function(…)
>>
>> { pos <- match('a', ...names())
>>
>>   if (is.na(pos))
>>
>> stop("a is required.")
>>
>>   …elt(pos)
>>
>> }
>>
>>
>>
>> Incidentally, what is the best way to extract the expression without
>> evaluating it?
>>
>>
>>
>> g <- function(...)
>>
>> { pos <- match('a',...names())
>>
&

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

2025-01-06 Thread Bert Gunter
I am frankly at a loss.

Have you read "An Introduction to R," which is shipped with R, especially
Ch. 10. Or any of Hadley's (free, online) books. Or looked at Posit's or
the web's tutorials? There is so much out there...

I would say that the Help docs are meant to be concise references on how to
use particular functions, *not* tutorials on how to write functions in R.
(That said, I have found some of R's Help resources sufficient to learn
techniques that I was ignorant of, regular expressions for example.
However, that is not their purpose, as I said).

Or have I entirely misunderstood you?!

NB. Terminology: Function "arguments" not "parameters". "Parameters"
actually means something different in R.

Cheers,
Bert

On Mon, Jan 6, 2025 at 3:26 PM Sorkin, John 
wrote:

> Bert and other on this Chain,
>
> The original question asked by Bert Gunter, highlights one of my long
> standing wishes. Perhaps my wish has already been fulfilled (if it has,
> please let me know where I can look of fulfill my wish), if it hasn't
> perhaps someone can grant me my wish.
>
> I have tried to understand how to write a function (beyond a basic
> function), get values of the parameters, and process the parameters. I have
> looked for a source that clearly describes how his may be done (with
> examples), but I have yet to find one. Yes, one can look at a function
> (e.g. lm) look at the statements that are used and use the help system to
> research each of the statements (I have done this), but doing this is not
> the most efficient way to learn the topic. It would be very helpful if
> someone Knowledgeable would put together a primer on writing functions and
> processing function arguments. If such a document exist, I would be happy
> to have someone send me its URL.
>
> Thank you,
> John
>
> John David Sorkin M.D., Ph.D.
> Professor of Medicine, University of Maryland School of Medicine;
> Associate Director for Biostatistics and Informatics, Baltimore VA Medical
> Center Geriatrics Research, Education, and Clinical Center;
> PI Biostatistics and Informatics Core, University of Maryland School of
> Medicine Claude D. Pepper Older Americans Independence Center;
> Senior Statistician University of Maryland Center for Vascular Research;
>
> Division of Gerontology and Paliative Care,
> 10 North Greene Street
> GRECC (BT/18/GR)
> Baltimore, MD 21201-1524
> Cell phone 443-418-5382
>
>
>
>
> ____________
> From: R-help  on behalf of Bert Gunter <
> [email protected]>
> Sent: Monday, January 6, 2025 5:22 PM
> To: Jorgen Harmse
> Cc: [email protected]
> Subject: Re: [R] Extracting specific arguments from "..."
>
> Thanks Jorgen.
>
> I thought your approach to getting the argument expressions was clever, but
> somewhat convoluted. I think the usual simple way is to use match.call()
> (or sys.call() )to get the unevaluated argument expressions;  e.g. ...
>
> f <- function(...){
>match.call()
> }
> > f(a = 'red', b = sin(zzz))
> f(a = "red", b = sin(zzz))
>
> The return value is an object of class call that can be subscripted as (or
> converted by as.list() to) a list to extract the argument expressions:
> > f(a = 'red', b = sin(zzz))$b
> sin(zzz)
>
> You'll note that the $b component is again of class "call". So you may wish
> to convert it to character or expression or whatever for further
> processing, depending on context. Obviously, I haven't thought about this
> carefully.
>
> You raise an important point about robustness. I believe this approach to
> extracting the call expressions should be fairly robust, but I do get
> confused about the lay of the land when you add promises with default
> arguments that may not yet have been forced before match.call() is called.
> You may have to wrestle with sys.call() and it's "wh" argument to make
> things work the way you want in that situation. I leave such delights to
> wiser heads, as well as any corrections or refinements to anything that
> I've said here.
>
> Cheers,
> Bert
>
> On Mon, Jan 6, 2025 at 9:55 AM Jorgen Harmse  wrote:
>
> > I think Bert Gunter is right, but do you want partial matches (not found
> > by match), and how robust do you want the code to be?
> >
> >
> >
> > f <- function(…)
> >
> > { pos <- match('a', ...names())
> >
> >   if (is.na(pos))
> >
> > stop("a is required.")
> >
> >   …elt(pos)
> >
> > }
> >
> >
> >
> > Incidentally, what is the best way to extract the

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

2025-01-06 Thread Sorkin, John
Bert and other on this Chain,

The original question asked by Bert Gunter, highlights one of my long standing 
wishes. Perhaps my wish has already been fulfilled (if it has, please let me 
know where I can look of fulfill my wish), if it hasn't perhaps someone can 
grant me my wish.

I have tried to understand how to write a function (beyond a basic function), 
get values of the parameters, and process the parameters. I have looked for a 
source that clearly describes how his may be done (with examples), but I have 
yet to find one. Yes, one can look at a function (e.g. lm) look at the 
statements that are used and use the help system to research each of the 
statements (I have done this), but doing this is not the most efficient way to 
learn the topic. It would be very helpful if someone Knowledgeable would put 
together a primer on writing functions and processing function arguments. If 
such a document exist, I would be happy to have someone send me its URL.

Thank you,
John

John David Sorkin M.D., Ph.D.
Professor of Medicine, University of Maryland School of Medicine;
Associate Director for Biostatistics and Informatics, Baltimore VA Medical 
Center Geriatrics Research, Education, and Clinical Center;
PI Biostatistics and Informatics Core, University of Maryland School of 
Medicine Claude D. Pepper Older Americans Independence Center;
Senior Statistician University of Maryland Center for Vascular Research;

Division of Gerontology and Paliative Care,
10 North Greene Street
GRECC (BT/18/GR)
Baltimore, MD 21201-1524
Cell phone 443-418-5382





From: R-help  on behalf of Bert Gunter 

Sent: Monday, January 6, 2025 5:22 PM
To: Jorgen Harmse
Cc: [email protected]
Subject: Re: [R] Extracting specific arguments from "..."

Thanks Jorgen.

I thought your approach to getting the argument expressions was clever, but
somewhat convoluted. I think the usual simple way is to use match.call()
(or sys.call() )to get the unevaluated argument expressions;  e.g. ...

f <- function(...){
   match.call()
}
> f(a = 'red', b = sin(zzz))
f(a = "red", b = sin(zzz))

The return value is an object of class call that can be subscripted as (or
converted by as.list() to) a list to extract the argument expressions:
> f(a = 'red', b = sin(zzz))$b
sin(zzz)

You'll note that the $b component is again of class "call". So you may wish
to convert it to character or expression or whatever for further
processing, depending on context. Obviously, I haven't thought about this
carefully.

You raise an important point about robustness. I believe this approach to
extracting the call expressions should be fairly robust, but I do get
confused about the lay of the land when you add promises with default
arguments that may not yet have been forced before match.call() is called.
You may have to wrestle with sys.call() and it's "wh" argument to make
things work the way you want in that situation. I leave such delights to
wiser heads, as well as any corrections or refinements to anything that
I've said here.

Cheers,
Bert

On Mon, Jan 6, 2025 at 9:55 AM Jorgen Harmse  wrote:

> I think Bert Gunter is right, but do you want partial matches (not found
> by match), and how robust do you want the code to be?
>
>
>
> f <- function(…)
>
> { pos <- match('a', ...names())
>
>   if (is.na(pos))
>
> stop("a is required.")
>
>   …elt(pos)
>
> }
>
>
>
> Incidentally, what is the best way to extract the expression without
> evaluating it?
>
>
>
> g <- function(...)
>
> { pos <- match('a',...names())
>
>   if (is.na(pos))
>
> stop("a is missing.")
>
>   (function(a,...) substitute(a)) (...)
>
> }
>
>
>
> Regards,
>
> Jorgen Harmse.
>
>
>
> Message: 8
> Date: Sun, 5 Jan 2025 11:17:02 -0800
> From: Bert Gunter 
> To: Iris Simmons 
> Cc: R-help 
> Subject: Re: [R] Extracting specific arguments from "..."
> Message-ID:
> <
> cagxfjbronopt-bodf6srpp79bwucppoo3+ycdgn3y-ytdu5...@mail.gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> Thanks, Iris.
> That is what I suspected, but it wasn't clear to me from the docs.
>
> Best,
> Bert
>
> On Sun, Jan 5, 2025 at 10:16 AM Iris Simmons  wrote:
> >
> > I would use two because it does not force the evaluation of the other
> arguments in the ... list.
> >
> >
> >
> > On Sun, Jan 5, 2025, 13:00 Bert Gunter  wrote:
> >>
> >> Consider:
> >>
> >> f1 <- function(...){
> >>   one <- list(...)[['a']]
> >>   two <- ...elt(match('a', ...names()))
> >>   c(one, two)
> >> 

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

2025-01-06 Thread Bert Gunter
Thanks Jorgen.

I thought your approach to getting the argument expressions was clever, but
somewhat convoluted. I think the usual simple way is to use match.call()
(or sys.call() )to get the unevaluated argument expressions;  e.g. ...

f <- function(...){
   match.call()
}
> f(a = 'red', b = sin(zzz))
f(a = "red", b = sin(zzz))

The return value is an object of class call that can be subscripted as (or
converted by as.list() to) a list to extract the argument expressions:
> f(a = 'red', b = sin(zzz))$b
sin(zzz)

You'll note that the $b component is again of class "call". So you may wish
to convert it to character or expression or whatever for further
processing, depending on context. Obviously, I haven't thought about this
carefully.

You raise an important point about robustness. I believe this approach to
extracting the call expressions should be fairly robust, but I do get
confused about the lay of the land when you add promises with default
arguments that may not yet have been forced before match.call() is called.
You may have to wrestle with sys.call() and it's "wh" argument to make
things work the way you want in that situation. I leave such delights to
wiser heads, as well as any corrections or refinements to anything that
I've said here.

Cheers,
Bert

On Mon, Jan 6, 2025 at 9:55 AM Jorgen Harmse  wrote:

> I think Bert Gunter is right, but do you want partial matches (not found
> by match), and how robust do you want the code to be?
>
>
>
> f <- function(…)
>
> { pos <- match('a', ...names())
>
>   if (is.na(pos))
>
> stop("a is required.")
>
>   …elt(pos)
>
> }
>
>
>
> Incidentally, what is the best way to extract the expression without
> evaluating it?
>
>
>
> g <- function(...)
>
> { pos <- match('a',...names())
>
>   if (is.na(pos))
>
> stop("a is missing.")
>
>   (function(a,...) substitute(a)) (...)
>
> }
>
>
>
> Regards,
>
> Jorgen Harmse.
>
>
>
> Message: 8
> Date: Sun, 5 Jan 2025 11:17:02 -0800
> From: Bert Gunter 
> To: Iris Simmons 
> Cc: R-help 
> Subject: Re: [R] Extracting specific arguments from "..."
> Message-ID:
> <
> cagxfjbronopt-bodf6srpp79bwucppoo3+ycdgn3y-ytdu5...@mail.gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> Thanks, Iris.
> That is what I suspected, but it wasn't clear to me from the docs.
>
> Best,
> Bert
>
> On Sun, Jan 5, 2025 at 10:16 AM Iris Simmons  wrote:
> >
> > I would use two because it does not force the evaluation of the other
> arguments in the ... list.
> >
> >
> >
> > On Sun, Jan 5, 2025, 13:00 Bert Gunter  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
> >>
> >> __
> >> [email protected] 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]]

__
[email protected] 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.


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

2025-01-06 Thread Jorgen Harmse via R-help
I think Bert Gunter is right, but do you want partial matches (not found by 
match), and how robust do you want the code to be?

f <- function(…)
{ pos <- match('a', ...names())
  if (is.na(pos))
stop("a is required.")
  …elt(pos)
}

Incidentally, what is the best way to extract the expression without evaluating 
it?



g <- function(...)

{ pos <- match('a',...names())

  if (is.na(pos))

stop("a is missing.")

  (function(a,...) substitute(a)) (...)

}

Regards,
Jorgen Harmse.

Message: 8
Date: Sun, 5 Jan 2025 11:17:02 -0800
From: Bert Gunter 
To: Iris Simmons 
Cc: R-help 
Subject: Re: [R] Extracting specific arguments from "..."
Message-ID:

Content-Type: text/plain; charset="utf-8"

Thanks, Iris.
That is what I suspected, but it wasn't clear to me from the docs.

Best,
Bert

On Sun, Jan 5, 2025 at 10:16 AM Iris Simmons  wrote:
>
> I would use two because it does not force the evaluation of the other 
> arguments in the ... list.
>
>
>
> On Sun, Jan 5, 2025, 13:00 Bert Gunter  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
>>
>> __
>> [email protected] 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]]

__
[email protected] 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.


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

2025-01-05 Thread Bert Gunter
Thanks, Iris.
That is what I suspected, but it wasn't clear to me from the docs.

Best,
Bert

On Sun, Jan 5, 2025 at 10:16 AM Iris Simmons  wrote:
>
> I would use two because it does not force the evaluation of the other 
> arguments in the ... list.
>
>
>
> On Sun, Jan 5, 2025, 13:00 Bert Gunter  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
>>
>> __
>> [email protected] 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.

__
[email protected] 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.


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

2025-01-05 Thread Iris Simmons
I would use two because it does not force the evaluation of the other
arguments in the ... list.



On Sun, Jan 5, 2025, 13:00 Bert Gunter  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
>
> __
> [email protected] 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]]

__
[email protected] 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.