Search code examples
scalaclojure

What are the differences between mapcat in Clojure and flatMap in Scala in terms of what they operate on?


I understand the equivalent to flatMap in Scala is mapcat in Clojure.

I have an inkling that mapcat in clojure only works with sequences, unlike flatMap in Scala which is more flexible.

My question is - what are the differences between mapcat in Clojure and flatMap in Scala in terms of what they operate on?

Assumptions:

  • I understand that Scala has a rich type system and Clojure has optional typing - I'm interested to know if the is a limitation in the parameters that mapcat accepts that make it only have a subset of flatMaps functionality.

Solution

  • The real difference is that flatMap is polymorphic on the type, and mapcat isn't. So any type can decide to provide a "flatMap" like behaviour. That's how you get things like Futures being flatMapable.

    In Clojure, mapcat is specific to the seqable type. Any seqable can be coerced into a sequence, and all sequence can be mapped and concatenated. The mapcat implementation will check if the input is seqable, if so, it will call seq on it to coerce it to a sequence, and then it will map and cat that sequence and give you back a sequence. You don't get back a result of the original type.

    In Scala, if you implement IterableLike trait (I think that's the right interface), you get the default flatMap implementation which is a bit like the Clojure one minus the coercion to sequence. But, many types also provide a custom implementation of flatMap, making it generic in that way.