Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Surprising behavior when performing flatmap on Maps whose values are Lists of 2-tuples #5364

Closed
scabug opened this issue Jan 10, 2012 · 7 comments
Assignees

Comments

@scabug
Copy link

scabug commented Jan 10, 2012

scala> val m = Map("a" -> List(11,111), "b" -> List(22,222))
m: scala.collection.immutable.Map[java.lang.String,List[Int]] = Map(a -> List(11, 111), b -> List(22, 222))

scala> m.flatMap(_._2) // Expected behavior
res9: scala.collection.immutable.Iterable[Int] = List(11, 111, 22, 222)

scala> val m = Map("a" -> List(1 -> 11,1 -> 111), "b" -> List(2 -> 22,2 -> 222))
m: scala.collection.immutable.Map[java.lang.String,List[(Int, Int)]] = Map(a -> List((1,11), (1,111)), b -> List((2,22), (2,222)))

scala> m.flatMap(_._2) // Surprising behavior, a map is created and 2 tuples are missing(overwritten)
res8: scala.collection.immutable.Map[Int,Int] = Map(1 -> 111, 2 -> 222)

@scabug
Copy link
Author

scabug commented Jan 10, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5364?orig=1
Reporter: Tom Dong (tomtung)
Affected Versions: 2.9.1

@scabug
Copy link
Author

scabug commented Jan 10, 2012

@paulp said:
This is how it works.

@scabug scabug closed this as completed Jan 10, 2012
@scabug
Copy link
Author

scabug commented Jan 10, 2012

Tom Dong (tomtung) said:
Can you please explain a little bit more? "Flat-mapping a map creates another map" does not make sense to me. To me, flat-mapping is breaking down the original collection, and concatenating the collections it contains to create a new collection. The original map does not contain any map, why should flatMap return a new Map, instead of List, which is what the original map actually contains?

@scabug
Copy link
Author

scabug commented Jan 10, 2012

@paulp said:
It doesn't matter what the map contains, or how you personally interpret flatmap - it matters that the operation is invoked on a map, and the result of the operation are elements which make another map. If you want a List, make it a List.

scala> m.toList flatMap (_._2)
res0: List[(Int, Int)] = List((1,11), (1,111), (2,22), (2,222))

@scabug
Copy link
Author

scabug commented Jan 10, 2012

Tom Dong (tomtung) said (edited on Jan 10, 2012 8:08:32 AM UTC):
Quote from "Programming in Scala" page 362:

(flatMap) applies the function to each list element and returns the concatenation of all function results.

So this is not my "personal" interpretation.

If you execute:
scala> m.map(_._2)
res10: scala.collection.immutable.Iterable[List[(Int, Int)]] = List(List((1,11), (1,111)), List((2,22), (2,222)))

You get a List of List, and concatenate them gives a List, not a Map.

"Operate on a collection, and get a new collection of the same type" seems to be a nice idea, but I don't think it automatically justifies the resultant semantic confusions. I think the problem here is that flatMapping a Map does not always return a Map. This happens only when the values of the map happens to be collections of 2-tuples - but 2-tuples are not exclusively used as Map elements. IMHO, this inconsistency can be problematic.

@scabug
Copy link
Author

scabug commented Jan 10, 2012

@paulp said:
I'm not saying it's perfect, I'm saying this is what is. It's fundamental to the design of the collections and changing it is way beyond what can be addressed in a ticket. Please take it up on one of the mailing lists.

@scabug
Copy link
Author

scabug commented Jan 10, 2012

Tom Dong (tomtung) said:
Oh, I see. I thought this were just an implementation issue of the flatMap operation. Thanks anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants