繁体   English   中英

如何使用 purrr::map(未迭代)附加 arguments?

[英]How to use purrr::map (not to be iterated) additional arguments?

我以为我已经了解如何使用purrr::map的附加 arguments 参数( ... )。 这是一些代码,希望能说明purrr::map的(对我而言)意外行为:

似乎在purrr::map参数a作为附加参数传递不起作用:

library(purrr)

f <- function(a, b) {
  a + b
}

g <- function(a = 0, b) {
  a + b
}

map(1:3, .f = ~ f(b = .x, a = 1))
#> [[1]]
#> [1] 2
#> 
#> [[2]]
#> [1] 3
#> 
#> [[3]]
#> [1] 4
map(1:3, .f = ~ f(b = .x), a = 1)
#> Error in f(b = .x): argument "a" is missing, with no default

map(1:3, .f = ~ g(b = .x, a = 1))
#> [[1]]
#> [1] 2
#> 
#> [[2]]
#> [1] 3
#> 
#> [[3]]
#> [1] 4
map(1:3, .f = ~ g(b = .x), a = 1)
#> [[1]]
#> [1] 1
#> 
#> [[2]]
#> [1] 2
#> 
#> [[3]]
#> [1] 3

lapply(1:3, function(b, a = 1) f(a, b))
#> [[1]]
#> [1] 2
#> 
#> [[2]]
#> [1] 3
#> 
#> [[3]]
#> [1] 4
lapply(1:3, function(b, a) f(a, b), a = 1)
#> [[1]]
#> [1] 2
#> 
#> [[2]]
#> [1] 3
#> 
#> [[3]]
#> [1] 4

我的问题是为什么代码:

map(1:3, .f = ~ f(b = .x), a = 1)

抛出错误?

我们可以在没有任何匿名 function 的情况下传递剩余的 arguments

library(purrr)
map(1:3, f, a = 1)
#[[1]]
#[1] 2

#[[2]]
#[1] 3

#[[3]]
#[1] 4

或者另一个选项是rlang::as_functionpurrr:as_mapper

map(1:3, as_mapper(f), a = 1)

或动态创建f

map(1:3, as_mapper(~ .x + .y), a = 1)

或者在调用中invoke

map(1:3, ~ invoke(f, b = .x, a = 1))
#[[1]]
#[1] 2

#[[2]]
#[1] 3

#[[3]]
#[1] 4

这将使它比.f = ~ f(b =.x), a = 1更容易阅读

在幕后, map() 调用 as_mapper() 我们可以手动执行此操作以查看发生了什么:

purrr::as_mapper( ~ f(b = .x, a = 1) )
# <lambda>
# function (..., .x = ..1, .y = ..2, . = ..1) 
# f(b = .x, a = 1)                                <----
# attr(,"class")
# [1] "rlang_lambda_function" "function"


purrr::as_mapper( ~ f(b = .x), a=1 )
# <lambda>
# function (..., .x = ..1, .y = ..2, . = ..1) 
# f(b = .x)                                       <----
# attr(,"class")
# [1] "rlang_lambda_function" "function"           

我强调了与<---的重要区别。 请注意,在第二种情况下,创建的 lambda function 没有包含您的额外a=1参数,这会导致您观察到的错误。

为了解决您的评论, a=1实际上正在传递给 lambda function。 你的 lambda function 只是没有做任何事情。 要正确合并a , lambda function 定义需要处理...点:

g <- function(a, b, ...) {a + b}               # ... are needed to catch all extra 
                                               #   arguments from as_mapper

purrr::as_mapper( .f = ~ g(b=.x, ...) )
# <lambda>
# function (..., .x = ..1, .y = ..2, . = ..1) 
# g(b = .x, ...)                               <-- dots are now forwarded to g()
# attr(,"class")
# [1] "rlang_lambda_function" "function"            

purrr::map(1:3, .f = ~ g(b=.x, ...), a=1 )     # a now properly gets passed to g
# [[1]]
# [1] 2
#
# [[2]]
# [1] 3
#
# [[3]]
# [1] 4

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM