[Rd] Low level subsetting and S3 subsetting

Antoine Fabri @nto|ne@|@br| @end|ng |rom gm@||@com
Thu Feb 29 13:30:59 CET 2024


Dear R-devel,

I periodically stumble on the same challenges when working with objects
with bracket S3 methods, and their length and names counterparts. I make
the distinction between what I call S3 subsetting using `[` and `[[` and
low level subsetting using `.subset()` and `.subset2()`.

When working with low level subsetting one has to be extremely careful,
because `length()`, `names()`, and `lapply()` (through the `as.list()`
method) are not guaranteed to work consistently (they are technically not
guaranteed to work consistently at the S3 level either but I reckon that
for a well designed class they should). Indeed AFAIK for the low level
length we need length(unclass(x)), for the low level names we need attr(x,
"names").

Assignment is another issue, we don't have `.subset<-` and `.subset2<-` so
we have to jump through many hoops to robustly assign to a deep nested
element in a classed list containing classed elements.

Interestingly, for loops work with low level subsetting, while lapply works
with S3 (and, fun fact, purrr::map works with low level subsetting too).

This idiom is robust with a consistent class, because lapply uses
`as.list()` : x[] <- lapply(x, fun)
But these are brittle, we're looping at a low level and assigning with S3
:: x[] <- purrr::map(x, fun)
for (i in x) {
  x[[i]] <- fun(x[[I]])
}

I wish we had some tools to manipulate data easily and safely at the low
level. Specifically I would like :
* A .names() function that returns attr(x,,"names")
* A .length() function that returns length(unclass(x)) efficiently
* .subset<-() and .subset2<-() functions to assign safely in nested objects
* An argument to lapply to allow looping at the low level (skip the
as.list() preprocessing)

Additionally, I recently realised that it is not easy with base R to
robustly check if an index exists in a list object (esp with low level
subsetting), I discuss it here :
https://twitter.com/antoine_fabri/status/1762802251305742404

An efficient helper function would be useful in base R IMO.

Many thanks,

Antoine

	[[alternative HTML version deleted]]



More information about the R-devel mailing list