22 Case study:
It’s useful to compare
purrr::pmap(). They both are an attempt to solve a similar problem, extending
map() to handle iterating over any number of arguments.
x <- c("apple", "banana", "cherry") pattern <- c("p", "n", "h") replacement <- c("x", "f", "q") mapply(gsub, pattern, replacement, x) #> p n h #> "axxle" "bafafa" "cqerry" mapply(gsub, pattern, replacement, x) #> p n h #> "axxle" "bafafa" "cqerry" purrr::pmap_chr(list(pattern, replacement, x), gsub) #>  "axxle" "bafafa" "cqerry"
Here we’ll ignore
simplify = TRUE which makes
mapply() type-unstable by default. I’ll also ignore
USE.NAMES = TRUE which isn’t just about using names, but about using character vector input as names for output. I think it’s reused from
lapply() without too much thought as it’s only the names of the first argument that matter.
mapply() takes the function to apply as the first argument, followed by an arbitrary number of arguments to pass to the function. This makes it different to the other
apply() functions (including
tapply()), which take the data as the first argument.
mapply() could take
... as the first arguments, but that would force
FUN to always be named, which would also make it inconsistent with the other
pmap() avoids this problem by taking a list of vectors, rather than individual vectors in
.... This allows
pmap() to use
... for another purpose, instead of the
MoreArg argument (a list),
... on to
There’s a subtle difference here that doesn’t matter in most cases - in the
fixed is recycled to the same length as
pattern whereas it is not
pmap(). TODO: figure out example where that’s more clear.
(Also note that
pmap() uses the
. prefix to avoid the problem described in Chapter 20.)