Reputation: 7768
How does immutable.Map.map work? It looks like there is something wrong with the documentation:
def map[B](f: (A) ⇒ B): Map[B]
[use case] Builds a new collection by applying a function to all elements of this immutable map.
Full Signature
def map[B, That](f: ((A, B)) ⇒ B)(implicit bf: CanBuildFrom[Map[A, B], B, That]): That
Map[B]
does not make sense since Map
takes two type parameters.B
the type argument of map
, and B
the type parameter of Map
.Upvotes: 1
Views: 82
Reputation: 7152
The understandable confusion stems from the fact that map
is not implemented in Map
, but in TraversableLike
. However, the function documentation in inherited by sub classes.
TraversableLike
takes two type parameters TraversableLike[+A, +Repr]
and the map function has the signature TraversableLike.map[B](f: (A) ⇒ B): Traversable[B]
. In the api docs of Map
the documentation for that is inherited and partly adjusted Traversable[B]
by Map[B]
, but B
from TraversableLike
is not resolved to (A, B)
form Map
.
(Might be a bug in Scaladoc, that probably won't be fixed, as there could be an erasure problem. But that's just guessing on my side.)
You can check what is actually implemented in Map
if you configure visibility of members right above the members documentation.
EDIT:
Now to your core question:
If the documentation would give us, what we could read intuitively
and if we simplify it a bit for readability
and if we than further use a bit more of natural language instead of acronyms, the signature of map for a Map[A, B]
could look like:
map[ResultItem, ResultCollection](f: (A,B) => ResultItem)(implicit bf: CanBuildFrom[Map[A, B], ResultItem, ResultCollection]): ResultCollection
So, basically you apply a function to each key-value-pair of the Map
that transforms a key-value-pair of type (A,B) into a value of type ResultType
.
As you can build almost any kind of collection from a map (or any other collection), this result type does not have to be another tuple. And ResultCollection
does not have to be another Map
. E.g.:
Map("1" -> 1, "2" -> 2).map((keyValuePair: (String, Int)) => keyValuePair._2)
or short
Map("1" -> 1, "2" -> 2).map(_._2)
has List(1, 2)
as result, List[Int]
as ResultCollection, Int
as ResultItem.
This is possible because of the implicit CanBuildFrom
parameter that adds an implicit builder that takes the result of the map function and appends it to its builder-result. In most cases CanBuildFrom
is inferred by the compiler. However, there are cases when it will not be able to infer the proper result collection.
In such cases you have to give the compiler more information:
val test2: Vector[Int] = Map("1" -> 1, "2" -> 2).map(_._2)(collection.breakOut)
val test3: Set[Int] = Map("1" -> 1, "2" -> 2).map(_._2)(collection.breakOut)
For more information on breakOut
and CanBuildFrom
I'd recommend this answer
Upvotes: 4