据我所知,除了简化之外,mapply
可以做的一切都可以用Map
完成。毕竟,Map
是mapply
的包装。然而,我很惊讶地看到,mapply
同时采用...
参数集(文档称为">参数来向量化(向量或严格正长度的列表,或全部为零长度)")和MoreArgs
参数在所需的函数f
之上,而Map
不使用MoreArgs
,只需要...
(文档只是称为">向量")和f
。
我的问题是:为什么mapply
需要MoreArgs
,而Map
不需要?mapply
可以做Map
不能做的事情吗?还是mapply
试图让Map
更难的事情变得更容易?如果有,那是什么?
我怀疑sapply
可能是一个有用的答案参考点。比较X
、FUN
和...
参数与mapply
的...
和MoreArgs
参数可能会有所帮助。
让我们看一下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
在r2.6中被引入,新闻条目如下:
新增高阶函数Reduce()、Filter()和Map()。
f
参数名在这些函数中是共享的,它们被记录在同一个页面上。我不知道为什么不把函数命名为FUN
,但这3个函数(以及?Reduce
中记录的其他函数)之间的一致性解释了为什么mapply
和Map
不以相同的方式命名它们的函数参数(一致性也解释了大写的M
)。
在文档中我们也可以读到:
Map
是mapply
的一个简单包装器,它不试图简化结果,类似于Common Lisp的mapcar(但是有循环的参数)。将来的版本可能允许对结果类型进行一些控制。
所以,理论上,正如我从最后一句话中理解的那样,Map
可以升级以提供一些类型稳定性,类似于vapply
所做的。在我看来,R-devel并没有走完全程,因为他们想要花时间来决定该做什么,从那时起他们就把它留在了这个状态。