我遇到了一个有趣的问题。我有三个变量的函数,让我们说(为了简单和透明)它是这样的:
my_fun <- function(a, b, c) paste(a, b, c, sep = '-')
我想为c
anb a
的多个组合创建仅包含参数b
的多个函数。我正在使用函数map2
和partial
(都来自包purrr
)。
require(purrr)
funs <- map2(letters[1:5], LETTERS[1:5], partial, ...f = my_fun)
我希望函数列表中的每个函数产生不同的输出,但事实并非如此。
funs[[1]]('hi') # [1] "e-E-hi"
funs[[3]]('hi') # [1] "e-E-hi"
funs[[5]]('hi') # [1] "e-E-hi"
我能够为我的问题创建不同的解决方案,所以我的问题不是&#34;如何做到&#34;。我很感兴趣为什么会这样做。
另一个使用基础mapply
的示例:
mapply(partial, letters[1:5], LETTERS[1:5], MoreArgs = list(...f = my_fun))[[1]]('hi')
# [1] "e-E-hi"
答案 0 :(得分:2)
问题源于partial
使用延迟评估这一事实,map2
表示存储.x
和.y
而不是a
, A
。幸运的是,有一个函数参数,我们可以使用:
funs <- map2(letters[1:5], LETTERS[1:5], partial, ...f = my_fun, .lazy = FALSE)
funs[[1]]('hi')
# [1] "a-A-hi"
如果您查看您的版本,我们会看到:
funs[[1]]
# function (...)
# my_fun(.x[[i]], .y[[i]], ...)
# <environment: 0x00000000201d9598>
其他每一个都是一样的。
现在,如果我们调查那个环境,我们可以看到:
ls(envir = environment(funs[[1]]))
# [1] "i"
因此有一个对象存储在i
,这将决定我们得到哪个.x
和.y
,其值是:
get('i', environment(funs[[1]]))
# [1] 5
另请注意,您的参数也存储在那里,但由于它们以.
开头而被隐藏:
ls(envir = environment(funs[[1]]), all.names = TRUE)
# [1] "..." ".f" ".x" ".y" "i"
get('.x', envir = environment(funs[[1]]))
# [1] "a" "b" "c" "d" "e"
因此,对于所有这些,我们得到相同的结果。具体来说,执行的调用最终是:
my_fun(letters[1:5][[5]], LETTERS[1:5][[5]], 'hi')
惰性评估在这里并不好用,并且在map2
内使用存储的内部循环计数器。