tl;dr If you want a vector result, use
mapv instead of
Much Clojure code involves the use of vectors.
And why not?
There’s a lot to love:
quick random access,
conj actually appends to the end. 😉
Vectors are so prevalent in Clojure code that there’s a version of
map designed just for them:
The practical difference is that,
rather than receiving a lazy sequence,
you get a fully realized vector.
(mapv f coll) case specifically,
mapv is also likely to be faster.
Let’s take a look at the source for
mapv to see why that is
(I’ve left out the docstring ’n’ metadata):
(defn mapv ([f coll] (-> (reduce (fn [v o] (conj! v (f o))) (transient ) coll) persistent!)) ([f c1 c2] (into  (map f c1 c2))) ([f c1 c2 c3] (into  (map f c1 c2 c3))) ([f c1 c2 c3 & colls] (into  (apply map f c1 c2 c3 colls))))
transient to set up a mutable vector,
persistent! on the result to return a normal, immutable vector back to the caller.
Transients are one of those nifty ways you can get your hands dirty with some mutation,
while the outside world is none the wiser.
Sometimes Clojure’s persistent data structures add non-trivial overhead,
and this can be a useful optimization—but as with a lot of performance “hacks”,
while it’s tempting to use this pattern everywhere,
perhaps wait to see if there’s actually a discernible problem first.
It’s interesting to note that all other forms of
mapv punt to regular
into  on the result.
I mean, that’s how I
mapv’d before I knew about
Nice to get some validation for my life choices. 🙂
which does what you might expect.
great for when you want a vector after a mapping operation.
Questions? Comments? Contact me!