【问题标题】:Now that invoke() is soft-deprecated, what's the alternative?现在 invoke() 已被软弃用,还有什么替代方案?
【发布时间】:2020-06-25 23:01:44
【问题描述】:

rlang::invoke() 现在已软弃用,purrr::invoke() 已停用。如今,以编程方式调用带有参数列表的函数的整洁方法是什么?

【问题讨论】:

  • 你能举一个具体的例子来说明你正在尝试做什么吗?可能没有完全替代品,但可能有替代品来做某件事。

标签: r functional-programming tidyverse


【解决方案1】:

tldr; 使用exec 而不是invoke;使用map2 加上exec 而不是invoke_map


invoke 的示例

退休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

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

invoke_map 的示例

同样,您可以将map2exec 一起使用,而不是invoke_map。以前,您可以使用 invoke_map 来使用具有不同参数集的函数

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

现在,将map2exec 一起使用

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

遗憾的是,map2 加上exec 语法不如invoke_map 简洁,但它可能更规范。

在使用map2exec 时可能有助于避免问题的一些cmets:

  1. map2 的第一个参数必须是 list。所以map2(list(rnorm), ...) 会起作用。仅提供map2(rnorm, ...) 的功能不会。这与invoke_map 不同,后者接受list 的函数和函数本身。
  2. 第二个参数必须是参数lists 的listmap2 将遍历顶层list,然后使用exec 内部的大爆炸运算符!!! 强制拼接函数参数的list

【讨论】:

  • 这个答案底部的评论,#2,非常非常重要。在发现参数本质上需要是“list(list(param))”之前,我只是浪费了一个小时的故障排除。这个答案非常有帮助。
【解决方案2】:

已经大约一年了,没有发布明确的替代品。我在这些场景中所做的是创建一个惰性函数调用并对其进行评估。这是一个很好的解耦invokeexec 没有,因为调用对象可以传递。

arglist <- list(n = 100, mean = 2, sd = 3)
aFunctionCall <- rlang::call2(rnorm, !!!arglist)

aFunctionCall
rlang::eval_bare(aFunctionCall)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-16
    • 2023-03-13
    • 2022-10-05
    • 2022-06-10
    • 2022-09-29
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    相关资源
    最近更新 更多