10

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.
11
  • 1
    What do you think a collection means in clojure? As it stands the "only works on collections" statement seems extremely odd, as I could not imagine what mapcat (or map even) would mean on something that cannot be treated as containing multiple values. Also map works on things like String that are not considered clojure collections, as well as all the collection types. Clojure is not optionally typed - static type checking is optional (and not in the core language) but there is no such thing as an untyped value in clojure. Commented Dec 4, 2013 at 2:24
  • Agree re 'collections' in Clojure - it was an answer here and I was trying to find out more about what was meant in case there was something I had missed: programmers.stackexchange.com/a/220150/13382 Commented Dec 4, 2013 at 2:45
  • Any object can implement ISeq and will then be a target for mapcat. Period. His assertion that mapcat does not use protocols is flat out 100% wrong. mapcat is implemented in terms of concat and map, both call seq on their args. seq works on anything that implements ISeq (with special cases for Java native objects that do not implement ISeq). Commented Dec 4, 2013 at 15:11
  • 1
    @noisesmith From clojuredocs.org/clojure_core/clojure.core/mapcat: "Thus function f should return a collection." Commented Dec 4, 2013 at 16:14
  • 3
    @noisesmith "I could not imagine what mapcat (or map even) would mean on something that cannot be treated as containing multiple values" Precisely. It's a part of the meaning of mapcat and map in Clojure, but it isn't a part of the meaning of flatMap and map in Scala. I am not saying that Clojure does anything wrong, worse than Scala, that it should have one name for these operations just because Scala does, etc. Commented Dec 4, 2013 at 16:19

4 Answers 4

5

I know a little about Scala but it seems to me flatMap is the Scala bind function in a monad and mapcat is a possible implementation of the bind function for the sequence monad in Clojure. So they are the same for sequences.

But Scala for example has a flatMap function for Futures: it takes a future and a mapping function and returns a future that will complete after input future completes. This operation doesn't seem to be a simple mapcat in Clojure. It may be realized this way instead

(defn flat-map [f mv] (mapcat (fn [v] (future (f @v))) mv))

So, no. They are not the same, neither in terms of what they operate on. In Scala flatMap is the common name for different functions and for example Futures' flatMap coordinates input and output futures. A simple mapcat in Clojure won't work because it won't return a future.

Sign up to request clarification or add additional context in comments.

2 Comments

"flatMap is the bind function in List monad" No, flatMap is the common Scala name for all bind functions.
@AlexeyRomanov thank you, I edited my answer according to your comment.
4

They seem very similar and appear to work on the same kind of things. From looking at the documentation and examples I can't see a functional difference.

mapcat works on sequences, and just about every clojure data type can be a sequence. If you pass something that is not already a seq to mapcat it will call seq on it automatically, so in practice you can pass just about all clojure values to mapcat. If you want to iterate over a tree you would need to call prewalk or postwalk to specify the traversal order.

1 Comment

"From looking at the documentation and examples I can't see a functional difference." See these examples instead: docs.scala-lang.org/overviews/core/futures.html
4

In the standard Scala library: Responder, Future, Parser, ControlContext. None of them are sequences or particularly sequence-like. There is also a slight variation in ParseResult.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.