问题
rlang::invoke() is now soft-deprecated, purrr::invoke() retired. These days, what is the tidy approach to programmatically calling a function with a list of arguments?
回答1:
tldr; Use exec instead of invoke; use map2 plus exec instead of invoke_map.
Example for invoke
With retired invoke
set.seed(2020)
invoke(rnorm, list(mean = 1, sd = 2), n = 10)
#[1] 1.7539442 1.6030967 -1.1960463 -1.2608118 -4.5930686 2.4411470
#[7] 2.8782420 0.5412445 4.5182627 1.2347336
With exec
set.seed(2020)
exec(rnorm, n = 10, !!!list(mean = 1, sd = 2))
#[1] 1.7539442 1.6030967 -1.1960463 -1.2608118 -4.5930686 2.4411470
#[7] 2.8782420 0.5412445 4.5182627 1.2347336
Example for invoke_map
Similarly, instead of invoke_map you'd use map2 with exec. Previously, you'd use invoke_map to use a function with different sets of arguments
set.seed(2020)
invoke_map(rnorm, list(list(mean = 0, sd = 1), list(mean = 1, sd = 1)), n = 10)
# [[1]]
# [1] 0.3769721 0.3015484 -1.0980232 -1.1304059 -2.7965343 0.7205735
# [7] 0.9391210 -0.2293777 1.7591313 0.1173668
#
# [[2]]
# [1] 0.1468772 1.9092592 2.1963730 0.6284161 0.8767398 2.8000431
# [7] 2.7039959 -2.0387646 -1.2889749 1.0583035
Now, use map2 with exec
set.seed(2020)
map2(
list(rnorm),
list(list(mean = 0, sd = 1), list(mean = 1, sd = 1)),
function(fn, args) exec(fn, n = 10, !!!args))
# [[1]]
# [1] 0.3769721 0.3015484 -1.0980232 -1.1304059 -2.7965343 0.7205735
# [7] 0.9391210 -0.2293777 1.7591313 0.1173668
#
# [[2]]
# [1] 0.1468772 1.9092592 2.1963730 0.6284161 0.8767398 2.8000431
# [7] 2.7039959 -2.0387646 -1.2889749 1.0583035
Sadly, the map2 plus exec syntax is not as concise as invoke_map, but it is perhaps more canonical.
A few comments that may help avoid issues when using map2 plus exec:
- The first argument of
map2must be alist. Somap2(list(rnorm), ...)will work. Just providing the function asmap2(rnorm, ...)will not. This is different toinvoke_map, which accepted both alistof functions and a function itself. - The second argument needs to be a
listof argumentlists.map2will iterate through the top-levellist, and then use the big-bang operator!!!insideexecto force-splice thelistof function arguments.
来源:https://stackoverflow.com/questions/60678764/now-that-invoke-is-soft-deprecated-whats-the-alternative