0

I have started learning Scala quite some time back and I did some reading on flatMap and flatten from the below two links.

The author takes the below code example,

 val fruits = Seq("apple", "banana", "orange")

and then uses flatMap on it.

fruits.flatMap(_.toUpperCase)

Also, the author says that map + flatten is flatMap with the below example.

def toInt(s: String): Option[Int] = {
        try {
            Some(Integer.parseInt(s.trim))
        } catch {
            // catch Exception to catch null 's'
            case e: Exception => None
        }
    }

val strings = Seq("1", "2", "foo", "3", "bar")
val mapResult = strings.map(toInt)
val flattenResult = mapResult.flatten

In both the examples I am confused on how it differs from flatten. Let's take the first example.

fruits.flatMap(_.toUpperCase)

This can also be computing using flatten as below and leading to the same result.

fruits.flatten(_.toUpperCase)

On the second example, it can be achieved with flatten also,

val flattenMap = strings.flatten(x=>toInt(x))

Since flatten is also a higher order function that takes in parameters, how is it different from flatMap ?

I can see that the source code is different for both the methods. I didn't dig deeper as I am yet to learn about co-variance, contra variance without which I wouldn't understand the collection source code.

Can anyone state a concrete example of where one would use flatten and flatMap ?

Greedy Coder
  • 1,256
  • 1
  • 15
  • 36
  • I don't understand the linked answer. If there is no difference then why two functions? There should be some difference atleast in terms of syntactic sugar and when to use? – Greedy Coder Nov 28 '17 at 18:00
  • 2
    "Since flatten is also a higher order function that takes in parameters" this is not true, `flatten` is not a higher-order function because it has no arguments. Your last two pieces of code are not correct (although the example above them *is* correct) `x.flatten` is completely equivalent to `x.flatMap(identity)`; it may be implemented differently for the sake of efficiency, but in terms of behavior they are the same. Interestingly, they are also [two isomorphic approaches](https://en.wikipedia.org/wiki/Monad_(functional_programming)#fmap_and_join) to define a monad. – Vladimir Matveev Nov 28 '17 at 18:32
  • @VladimirMatveev : I am confused here. The above code I used is valid syntax and it works. By wrong you mean it is wrong to use that method in the coding style sense? I am just finding it difficult to visualize the difference, so I am searching for a good code example. I understand the part where x.flatten is equivalent to x.map and then flatten. The difference between flatMap and flatten is what I am trying to understand. – Greedy Coder Nov 29 '17 at 05:43
  • I meant x.flatMap is equivalent to x.map and then flatten. When you meant that x.flatten is not a higher order function then why does it take an argument as above. It does take in a function just like like flatMap – Greedy Coder Nov 29 '17 at 05:58
  • 1
    `flatten` does not take an explicit argument, see its [documentation](http://www.scala-lang.org/api/current/scala/collection/Traversable.html#flatten[B]:Traversable[B]). What it does take is an implicit argument which converts each element of the collection into another collection - this is necessary because flattening can only happen if items of a collection are collection-like themselves. Curiously, I can now see why it works for you - this definition makes it having almost the same meaning as `flatMap`. This is definitely not how it is intended to be used, though. – Vladimir Matveev Nov 29 '17 at 11:43
  • 1
    What I mean is that `flatten` accepting an implicit function as an argument is a purely technical detail needed to handle situations of flattening collections like `Vector[Option[Int]]` or `Vector[String]` (where internal elements do not extend any collection traits, but do have an implicit conversion to a collection). If you ignore this technical detail, then `flatten` is a bit more specific than `flatMap`. – Vladimir Matveev Nov 29 '17 at 11:45
  • Ah. I see. The implicit makes sense now and I am able to understand the difference. The example confused me even more. Thanks for taking the time to explain. – Greedy Coder Nov 29 '17 at 11:51

0 Answers0