Now that invoke() is soft-deprecated, what's the alternative?

后端 未结 1 1631
渐次进展
渐次进展 2021-01-25 10:27

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条回答
  • 2021-01-25 10:55

    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:

    1. The first argument of map2 must be a list. So map2(list(rnorm), ...) will work. Just providing the function as map2(rnorm, ...) will not. This is different to invoke_map, which accepted both a list of functions and a function itself.
    2. The second argument needs to be a list of argument lists. map2 will iterate through the top-level list, and then use the big-bang operator !!! inside exec to force-splice the list of function arguments.
    0 讨论(0)
提交回复
热议问题