我们来看Map的代码:
Map
function (f, ...)
{
f <- match.fun(f)
mapply(FUN = f, ..., SIMPLIFY = FALSE)
}
正如你所写,它只是一个包装器,点被转发到mapply,注意SIMPLIFY 被硬编码为FALSE
为什么mapply需要MoreArgs而Map不需要?
这是一个设计选择,可能部分是由于历史原因,我不会介意明确的 MoreArgs 和 USE.NAMES 参数(或 SIMPLIFY = TRUE 参数),但我相信理由是Map 很简单,如果您想调整参数,建议您使用mapply。不过,您可以将MoreArgs 和USE.NAMES 与Map 一起使用,它们将通过点传递到mapply 调用,尽管它没有记录,因为文档将... 参数描述为“向量”。
Map(sum, setNames(1:2, c("a", "b")), 1:2)
#> $a
#> [1] 2
#>
#> $b
#> [1] 4
Map(sum, setNames(1:2, c("a", "b")), 1:2, USE.NAMES = FALSE)
#> [[1]]
#> [1] 2
#>
#> [[2]]
#> [1] 4
Map(
replicate,
2:3,
c(FALSE, TRUE),
MoreArgs = list(expr = quote(runif(1))))
#> [[1]]
#> [[1]][[1]]
#> [1] 0.7523955
#>
#> [[1]][[2]]
#> [1] 0.4922519
#>
#>
#> [[2]]
#> [1] 0.81626690 0.07415023 0.56264388
等效的mapply 调用将是:
mapply(sum, setNames(1:2, c("a", "b")), 1:2, SIMPLIFY = FALSE)
#> $a
#> [1] 2
#>
#> $b
#> [1] 4
mapply(sum, setNames(1:2, c("a", "b")), 1:2, USE.NAMES = FALSE, SIMPLIFY = FALSE)
#> [[1]]
#> [1] 2
#>
#> [[2]]
#> [1] 4
mapply(
replicate,
2:3,
c(FALSE, TRUE),
MoreArgs = list(expr = quote(runif(1))))
#> [[1]]
#> [[1]][[1]]
#> [1] 0.6690229
#>
#> [[1]][[2]]
#> [1] 0.7529774
#>
#>
#> [[2]]
#> [1] 0.8632736 0.7822639 0.8553680
mapply 可以做 Map 做不到的事情吗?还是 mapply 试图让使用 Map 更难的事情变得更容易?如果有,是什么?
您不能将SIMPLIFY 与Map 一起使用:
Map(sum, 1:3, 1:3, SIMPLIFY = TRUE)
#> Error in mapply(FUN = f, ..., SIMPLIFY = FALSE): formal argument "SIMPLIFY" matched by multiple actual arguments
一点历史
-
mapply 是在 R 1.7.0 中引入的
-
Map 是在 R 2.6 中引入的,NEWS 项目如下:
新的高阶函数 Reduce()、Filter() 和 Map()。
f 参数名称在这些函数之间共享,并且它们记录在同一页面上。我不知道为什么不使用命名函数 FUN 的原因,但是这 3 个函数(以及 ?Reduce 中记录的其他函数)之间的一致性解释了为什么 mapply 和 Map 不命名它们的函数参数同样的方式(一致性解释了大写M 我猜也是)。
在文档中我们也可以阅读:
Map 是mapply 的简单包装器,它不尝试简化结果,类似于 Common Lisp 的 mapcar(不过,参数被回收)。未来的版本可能允许对结果类型进行一些控制。
所以,理论上,正如我从最后一句中了解到的,Map 可以升级以提供某种类型稳定性,类似于vapply 所做的。在我看来,R-devel 并没有一路走下去,因为他们想花时间正确地决定要做什么,从那时起他们就一直处于这种状态。