2

When I look a the Map.map scaladoc, I can see

map[B](f: (A) ⇒ B): Map[B]

But the simple following code doesn't return a Map

scala> Map("answer" -> 42).map { case(k, v) => v }
res40: scala.collection.immutable.Iterable[Int] = List(42)

Can you explain ?

Yann Moisan
  • 8,161
  • 8
  • 47
  • 91

2 Answers2

3

Scaladocs are simplified, if you want to see the full signature you have to expand and click on show full signature and you'll see that the real one is this:

def map[B, That](f: ((A, B)) ⇒ B)(implicit bf: CanBuildFrom[Map[A, B], B, That]): That

Which allows to return a That which can be a Map but also a List.

Ende Neu
  • 15,581
  • 5
  • 57
  • 68
  • What is a "`That`"? A quick Google didn't reveal anything (likely because "that" is too common a word). Is it an explicit supertype of a `List` or a `Map`? Or some sort of generic abstraction? If I see `That` in a scaladoc, what can I infer about the type? – dimo414 Sep 28 '14 at 21:55
  • 1
    Don't be confused by the word, `That` here is a type parameter, it could have been named `T`, or `FVG` or wathever, in this context it simply denotes the return type of the `map`. To make a simpler example `def someMethod[T](value: T): T = value`, here you can say that this methods returns a `T` because `T` is the return type specified in the signature, I could have called `That` if I wanted to: `def someMethod[That](value: That): That = value` – Ende Neu Sep 28 '14 at 21:58
  • Gotcha, but then what types can `That` actually be in this case? I don't immediately see any bounds defining what types `That` can be. Put another way, how is `That` different than `AnyRef` here? – dimo414 Sep 28 '14 at 22:23
  • 2
    Although the type in unconstrained there's an implicit `CanBuildFrom` used to specify whether a type can be build from another, the first type parameter is the from part (in this case we are mapping a `Map[A, B]` and the third parameter is the collection we want to end up with (in the method is `That` in this question in particular it's a `List`). [This blog post](http://www.dotkam.com/2012/05/08/scala-fun-with-canbuildfrom/) explains the `CanBuildFrom` in more details, there are anyway a lot of resources on the matter. – Ende Neu Sep 28 '14 at 22:31
  • 2
    "Simplified" implies a transformation that preserves some sort of correctness. Scaladocs aren't simplified; they're just wrong. `Map[B]` can't even be a type. It makes no sense whatsoever. – Chris Martin Sep 29 '14 at 00:18
  • @ChrisMartin I agree, I was being generous calling it simplified. – Ende Neu Sep 29 '14 at 07:59
  • I don't understand the full signature. Why it's `f: ((A, B)) ⇒ B` instead of `f: ((A, B)) ⇒ C` – Yann Moisan Jun 22 '15 at 20:04
  • @YannMoisan the scaladoc is flawed, you shouldn't eve look at it, it's better o look at the source dode, this is the actual signature: `def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That`. – Ende Neu Jun 22 '15 at 20:42
2

The simple answer is that you need key-value pairs to build Maps.

scala> Map("answer" -> 42).map { case(k, v) => (k, 43) }
res6: scala.collection.immutable.Map[String,Int] = Map(answer -> 43)
som-snytt
  • 39,429
  • 2
  • 47
  • 129