minimap

minimap provides purrr-style mapping functions – mmap_map(), mmap_map2(), mmap_imap(), mmap_walk(), mmap_iwalk(), and the type-stable mmap_map_dbl()/mmap_map_lgl()/mmap_map_chr() – built entirely on lapply()/vapply(). See the README for the full API reference and scope notes; this page walks through each one, starting from the basic case and building up to the two-input and side-effect variants.

Functions

Core functions

  • mmap_map(.x, .f) – apply .f to each element of .x, always returning a list, with names preserved.
  • mmap_map_dbl()/mmap_map_lgl()/mmap_map_chr() – like mmap_map(), but return an atomic vector of the named type instead of a list, via vapply().
  • mmap_map2(.x, .y, .f) – apply .f to corresponding pairs of elements from two same-length lists/vectors.
  • mmap_imap(.x, .f) – apply .f to each element of .x together with its name.
  • mmap_walk(.x, .f) – like mmap_map(), but for side effects only: returns .x invisibly instead of the results.
  • mmap_iwalk(.x, .f) – like mmap_imap(), but for side effects only: returns .x invisibly instead of the results.

Internal helpers

  • .mmap_assert(expr, message) – a small argument-checking helper built on base stop(), used to validate inputs like matching lengths or the presence of names.

mmap_map()

mmap_map() is the workhorse of the mini: apply a function to each element of a list or atomic vector, and get back a list of results the same length, with any names from the input preserved on the output. It’s a thin wrapper around lapply(), so anything you already know about lapply()’s behaviour carries over directly:

mmap_map(1:3, function(x) x + 1)
[[1]]
[1] 2

[[2]]
[1] 3

[[3]]
[1] 4
mmap_map(c(a = 1, b = 2), function(x) x * 10)
$a
[1] 10

$b
[1] 20

Because the return type is always a list, mmap_map() is safe to use even when .f returns different types or lengths for different elements:

mmap_map(1:3, function(x) if (x == 2) c(x, x) else x)
[[1]]
[1] 1

[[2]]
[1] 2 2

[[3]]
[1] 3

Type-stable variants

Often you know in advance that every element of the result will be a single number, logical, or string – in which case getting a list back is inconvenient. mmap_map_dbl(), mmap_map_lgl(), and mmap_map_chr() cover that case: they behave like mmap_map(), but return an atomic vector of the named type via vapply(), which also means they validate that every call to .f really does produce a length-1 value of the expected type:

mmap_map_dbl(1:3, function(x) x + 1)
[1] 2 3 4
mmap_map_lgl(1:5, function(x) x %% 2 == 0)
[1] FALSE  TRUE FALSE  TRUE FALSE
mmap_map_chr(c(a = 1, b = 2), function(x) sprintf("value is %s", x))
           a            b 
"value is 1" "value is 2" 

If .f breaks that promise – by returning a vector of length 2 instead of 1, say – the call errors immediately rather than silently producing a malformed or recycled result:

mmap_map_dbl(1:3, function(x) c(x, x))
Error in `vapply()`:
! values must be length 1,
 but FUN(X[[1]]) result is length 2

mmap_map2() and mmap_imap()

Sometimes one input isn’t enough. mmap_map2() walks two same-length vectors in parallel, calling .f with one element from each:

mmap_map2(1:3, 4:6, function(x, y) x + y)
[[1]]
[1] 5

[[2]]
[1] 7

[[3]]
[1] 9

Passing vectors of mismatched length is a deliberate error rather than silent recycling:

mmap_map2(1:3, 1:2, function(x, y) x + y)
Error:
! `.x` and `.y` must have the same length

mmap_imap() covers a related but different need: walking a single named vector together with its own names, rather than a second vector. .f is called with the element first, then its name:

mmap_imap(c(a = 1, b = 2), function(val, name) paste0(name, "=", val))
$a
[1] "a=1"

$b
[1] "b=2"

.x must actually be named for mmap_imap() to make sense, and that’s enforced:

mmap_imap(1:3, function(val, name) paste0(name, "=", val))
Error:
! `.x` must be named

mmap_walk() and mmap_iwalk()

mmap_map() and mmap_imap() are for when you want the results. mmap_walk() and mmap_iwalk() are their side-effect-only counterparts: same iteration behaviour, but the return value is .x itself, returned invisibly, so they compose neatly at the end of a pipeline without cluttering the console with the results of every call to .f:

mmap_walk(1:3, function(x) cat("value:", x, "\n"))
value: 1 
value: 2 
value: 3 
mmap_iwalk(c(a = 1, b = 2), function(val, name) cat(name, "->", val, "\n"))
a -> 1 
b -> 2 

Because the input is returned invisibly, mmap_walk()/mmap_iwalk() can be dropped into the middle of a longer expression purely for their printing side effect, without changing what the expression evaluates to:

result <- mmap_walk(1:3, function(x) cat("processing", x, "\n"))
processing 1 
processing 2 
processing 3 
identical(result, 1:3)
[1] TRUE