The vecvec_mapply() function applies a function .f across the vectors in .l, combining the results into a vecvec that preserves the original (possibly heterogeneous) type of each element of any vecvec inputs. Unlike mapply()/Map(), .f is not called once per logical element - it is called once per contiguous run of positions that draw from the same combination of underlying storage slots across every vector in .l (the same slot-grouping used internally for Ops.vecvec::vecvec, e.g. +/==). Each call therefore receives one vector per element of .l (that group's values) rather than one scalar per element of .l, so .f must itself be vectorised - an ordinary operator or vectorised function (e.g. +, paste0) qualifies automatically, but .f must return a result the same length as its inputs, or vecvec_mapply() errors.

vecvec_mapply(.l, .f, ..., ptype = NULL, SIMPLIFY = !is.null(ptype))

Arguments

.l

A list of vectors to apply .f over. Elements of .l may be vecvec objects or plain vectors; plain vectors are treated as if wrapped with vecvec(). All vectors in .l are recycled to a common size following vctrs::vec_recycle_common() rules.

.f

A vectorised function, applied once per group of positions that share the same underlying storage slots across every vector in .l. Called with one vector per element of .l (that group's values) plus ....

...

Additional arguments passed to every call of .f.

ptype

A prototype to simplify the result to with unvecvec(). If NULL and SIMPLIFY is TRUE, the common type is inferred from the result as in unvecvec().

SIMPLIFY

If TRUE, unvecvec() is applied to the result, using ptype as the target type. If FALSE, the result is always a vecvec object.

Value

A vecvec object combining the results of calling .f on each group of positions of .l, or (if SIMPLIFY is TRUE) that result simplified to a single type with unvecvec(). Positions where any input has a missing (NA) index form their own group and are not passed to .f at all - they come back as NA directly, matching how missing elements are treated elsewhere (e.g. vecvec_apply(), [<-, is.na<-).

Details

Because the number of calls to .f scales with the number of distinct slot combinations rather than with length(.l[[1]]), this is cheap for structured or replicated inputs (few distinct slot combinations) and degrades toward one call per element only in the worst case (every position drawing from a different combination of slots) - the same cost profile as vecvec_apply() and Ops.vecvec::vecvec, and unlike a plain mapply()/Map() call, which always calls .f once per element.

See also

vecvec_apply() for the single-input equivalent, applying .f once per underlying storage vector of a single vecvec. Ops.vecvec::vecvec uses the same slot-grouping strategy for arithmetic/comparison operators.