Let's look at the code of Map
:
Map
function (f, ...)
{
f <- match.fun(f)
mapply(FUN = f, ..., SIMPLIFY = FALSE)
}
As you wrote, it's just a wrapper, and the dots are forwarded to mapply
, note that SIMPLIFY
is hardcoded to FALSE
Why does mapply need MoreArgs
but Map
doesn't?
It's a design choice, possibly due in part to historical reasons, I wouldn't have minded explicit MoreArgs
and USE.NAMES
arguments (or a SIMPLIFY = TRUE
argument for that matter), but I believe the rationale is that Map
is meant to be simple, if you want to tweak parameters you're encouraged to use mapply
. Nevertheless, you can use MoreArgs
and USE.NAMES
with Map
, they will travel through the dots to the mapply
call, though it is undocumented, as the doc describes the ...
argument as "vectors".
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
The equivalent mapply
calls would be :
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?
You cannot use SIMPLIFY
with Map
:
Map(sum, 1:3, 1:3, SIMPLIFY = TRUE)
#> Error in mapply(FUN = f, ..., SIMPLIFY = FALSE): formal argument "SIMPLIFY" matched by multiple actual arguments
a bit of history
mapply
was introduced with R 1.7.0
Map
was introduced with R 2.6, the NEWS item reads :
New higher-order functions Reduce(), Filter() and Map().
The f
argument name is shared among those functions and they are documented on the same page. The reason why moving away from naming functions FUN
is unknown to me, but the consistency between these 3 functions (and the other functions documented in ?Reduce
) explains why mapply
and Map
don't name their function argument the same way (the consistency explains the upper case M
too I guess).
In the doc we can also read :
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.
So, in theory, as I understand from the last sentence, Map
could be upgraded to provide some type stability, similar to what vapply
does. It seems to me that R-devel didn't go all the way because they wanted to take time to decide properly what to do, and they left it in this state since then.