r语言 - 为什么Map只需要一组vector作为实参,而mapply需要这两组和MoreArgs实参? &



据我所知,除了简化之外,mapply可以做的一切都可以用Map完成。毕竟,Mapmapply的包装。然而,我很惊讶地看到,mapply同时采用...参数集(文档称为">参数来向量化(向量或严格正长度的列表,或全部为零长度)")和MoreArgs参数在所需的函数f之上,而Map不使用MoreArgs,只需要...(文档只是称为">向量")和f

我的问题是:为什么mapply需要MoreArgs,而Map不需要?mapply可以做Map不能做的事情吗?还是mapply试图让Map更难的事情变得更容易?如果有,那是什么?

我怀疑sapply可能是一个有用的答案参考点。比较XFUN...参数与mapply...MoreArgs参数可能会有所帮助。

让我们看一下Map的代码:

Map
function (f, ...) 
{
f <- match.fun(f)
mapply(FUN = f, ..., SIMPLIFY = FALSE)
}

正如你所写的,它只是一个包装器,点被转发到mapply,注意SIMPLIFY是硬编码到FALSE

为什么mapply需要MoreArgsMap不需要?

这是一个设计选择,可能部分是由于历史原因,我不会介意明确的MoreArgsUSE.NAMES参数(或SIMPLIFY = TRUE参数),但我认为基本原理是Map意味着简单,如果你想调整参数,你被鼓励使用mapply。尽管如此,您可以将MoreArgsUSE.NAMESMap一起使用,它们将通过点传递到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中记录的其他函数)之间的一致性解释了为什么mapplyMap不以相同的方式命名它们的函数参数(一致性也解释了大写的M)。

在文档中我们也可以读到:

Mapmapply的一个简单包装器,它不试图简化结果,类似于Common Lisp的mapcar(但是有循环的参数)。将来的版本可能允许对结果类型进行一些控制。

所以,理论上,正如我从最后一句话中理解的那样,Map可以升级以提供一些类型稳定性,类似于vapply所做的。在我看来,R-devel并没有走完全程,因为他们想要花时间来决定该做什么,从那时起他们就把它留在了这个状态。

最新更新