Feature request: `Vectorize()` alternative
lhdjung opened this issue · comments
Lukas Jung commented
I wonder if this might be within scope for purrr – sorry if not.
base::Vectorize()
has some shortcomings:
- Its output functions simplify their own output by default if they are closures.
- Functions with no arguments, or with
…
as their only argument, are silently returned unchanged. With closures, perhaps this should be an error since they really don't have any arguments to vectorize over. With primitives, any non-dots arguments don't count even if they behave as such. Therefore, ifFUN
is a primitive with one or more non-dots arguments, it might be preferable to consistently return a vectorized closure that wraps the input. Other primitives should probably be errors. Returning the input function unchanged is a problem especially for those primitives that are not vectorized by themselves:
vectorized_length <- Vectorize(length)
identical(length, vectorized_length)
#> [1] TRUE
# Here, the user may expect `c(a = 10L, b = 26L, c = 1L)`:
vectorized_length(list(a = 1:10, b = letters, c = TRUE))
#> [1] 3
Created on 2023-05-05 with reprex v2.0.2
- (Assuming
FUN
is a closure with at least one non-dots argument:) The body of each output function is identical, and it's quite hard to read. This may be confusing, especially because the input function never visibly appears in the output function. This also means it's not useful to copy and paste the printed output function into one's source code. - The arguments are suboptimally named.
vectorize.args
might be renamed toover
, as in "functionf()
is vectorized over its argumentx
".
Zeng Guangyu commented
I also vote for adding this feature for purrr
. And in addition to the shortcomings @lhdjung suggested, base::Vectorize()
also lacks the option to add a progress bar to the resulting function, which I think can be useful.
Hadley Wickham commented
I think this is out of scope for purrr, since it's relatively straight forward to do by hand:
vectorized_length <- function(x) {
map_int(x, length)
}
And defining a function that has enough parameters to vectorise a function in every way that someone might want it is going to be hard.