[Rd] [WARNING: POTENTIAL FORGED EMAIL] Augment base::replace(x, list, value) to allow list= to be a predicate?
Pavel Krivitsky
p@kr|v|t@ky @end|ng |rom un@w@edu@@u
Sun Mar 19 07:33:38 CET 2023
Dear All,
Following up on this, I was wondering whether it might be possible to
get a disposition from R developers.
I did find a way to produce a similar effect reasonably concisely using
call alchemy and lazy evaluation. The following function grabs the
specified arguments in the function whose argument it is, applies the
specified function to them, and returns the result. I am not sure if it
correctly handles all possible cases, particularly when nonstandard
evaluation and functions with side-effects are involved.
.af. <- function(...){
if(is.numeric(arg1 <- ...elt(1)) || is.character(arg1)){ # By position or name
i <- arg1
f <- ...elt(2L)
g <- \(x, dummy1, dummy2, ...) f(x, ...) # Eat 2 arguments in ... .
}else{ # First argument (the default)
i <- 1L
f <- arg1
g <- \(x, dummy, ...) f(x, ...) # Eat 1 argument in ... .
}
sys.function(1L) |> formals() |> names() |>
setNames(nm=_) |> (`[`)(i) |> get(sys.frame(1L)) |>
g(...)
}
# Examples:
c(1,2,NA,3) |> replace(.af.(is.na), 0) # First argument
1:5 |> replace(.af.(`>`, 3), 0) # Function of multiple arguments
1:5 |> ifelse(.af.(2, `>`, 3), yes=_, 0) # Specify position of referenced argument
1:5 |> ifelse(.af.("yes", `>`, 3), yes=_, 0) # Specify name of referenced argument
It may also make sense to have hard-coded versions of this for common cases, e.g.,
.a2f. <- function(...) .af.(2L, ...)
I am not sure how readable or concise this is in practice, and I don't
think this should go into R proper, but would anyone else use it if I
put something like this in a package?
Best Regards,
Pavel
On Sat, 2023-03-04 at 00:21 +0000, r-devel-bounces using r-project.org wrote:
> Dear All,
>
> Currently, list= in base::replace(x, list, value) has to be an index
> vector. For me, at least, the most common use case is for list= to be
> some simple property of elements of x, e.g.,
>
> x <- c(1,2,NA,3)
> replace(x, is.na(x), 0)
>
> Particularly when using R pipes, which don't allow multiple
> substitutions, it would simplify many of such cases if list= could be
> a
> function that returns an index, e.g.,
>
> replace <- function (x, list, values, ...) {
> # Here, list() refers to the argument, not the built-in.
> if(is.function(list)) list <- list(x, ...)
> x[list] <- values
> x
> }
>
> Then, the following is possible:
>
> c(1,2,NA,3) |> replace(is.na, 0)
>
> Any thoughts?
> Pavel
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
More information about the R-devel
mailing list