为什么 Map 只需要一组向量作为参数,而 mapply 需要这两个参数和 MoreArgs 参数?

Why does Map only require one set of vectors as arguments, but mapply requires both that and the MoreArgs argument?

据我所知,除了简化之外,mapply能做到的一切,Map都能做到。毕竟,Mapmapply 的包装器。但是,我很惊讶地看到 mapply 接受了两个 ... 参数集(文档称之为“ arguments to vectorize over (vectors or lists of strictly positive length, or all零长度)")和一个 MoreArgs 参数在所需函数 f 之上,而 Map 不使用 MoreArgs,只需要 ...(文档只是调用“vectors”)和 f.

我的问题是:为什么 mapply 需要 MoreArgsMap 不需要? mapply 可以做一些 Map 做不到的事情吗?还是 mapply 试图让 Map 变得更难的事情变得更简单?如果是,那是什么?

我怀疑 sapply 可能是一个有用的答案参考点。将其 XFUN... 参数与 mapply...MoreArgs.

进行比较可能会有所帮助

我们来看一下Map的代码:

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

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

Why does mapply need MoreArgs but Map doesn't?

这是一种设计选择,可能部分是由于历史原因,我不会介意明确的 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

Can mapply do something that Map cannot? Or is mapply trying to make something easier that would be harder with Map? And if so, what?

您不能将 SIMPLIFYMap 一起使用:

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 中引入的,新闻条目为:

New higher-order functions Reduce(), Filter() and Map().

f 参数名称在这些函数之间共享,并且它们记录在同一页面上。我不知道为什么放弃命名函数 FUN 的原因,但这 3 个函数(以及 ?Reduce 中记录的其他函数)之间的一致性解释了为什么 mapplyMap 不要以相同的方式命名它们的函数参数(我猜一致性也解释了大写 M)。

在文档中我们还可以阅读:

Map is a simple wrapper to mapply which does not attempt to simplify the result, similar to Common Lisp's mapcar (with arguments being recycled, however). Future versions may allow some control of the result type.

因此,理论上,正如我从最后一句话中了解到的那样,Map 可以升级以提供某种类型稳定性,类似于 vapply 所做的。在我看来,R-devel 并没有一路走下去,因为他们想花时间来适当地决定做什么,然后就把它留在了这个状态。