La réponse se trouve sur la définition de map:
def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That 
Notez qu'il a deux paramètres. Le premier est votre fonction et le second est implicite. Si vous ne fournissez pas cela implicitement, Scala choisira celui le plus spécifique disponible.
À propos breakOut
Alors, quel est le but de breakOut? Considérez l'exemple donné pour la question, vous prenez une liste de chaînes, transformez chaque chaîne en un tuple (Int, String), puis produisez-en une Map. La façon la plus évidente de le faire serait de produire une List[(Int, String)]collection intermédiaire , puis de la convertir.
Étant donné que maputilise un Builderpour produire la collection résultante, ne serait-il pas possible de sauter l'intermédiaire Listet de collecter les résultats directement dans un Map? Évidemment, oui. Pour ce faire, cependant, nous devons passer un bon CanBuildFromà map, et c'est exactement ce qui breakOutfait.
Examinons donc la définition de breakOut:
def breakOut[From, T, To](implicit b : CanBuildFrom[Nothing, T, To]) =
  new CanBuildFrom[From, T, To] {
    def apply(from: From) = b.apply() ; def apply() = b.apply()
  }
Notez qu'il breakOutest paramétré et qu'il renvoie une instance de CanBuildFrom. En l'occurrence, les types From, Tet Toont déjà été déduits, parce que nous savons que cela mapattend CanBuildFrom[List[String], (Int, String), Map[Int, String]]. Par conséquent:
From = List[String]
T = (Int, String)
To = Map[Int, String]
Pour conclure, examinons l'implicite reçu par breakOutlui-même. C'est de type CanBuildFrom[Nothing,T,To]. Nous connaissons déjà tous ces types, nous pouvons donc déterminer que nous avons besoin d'un implicite de type CanBuildFrom[Nothing,(Int,String),Map[Int,String]]. Mais existe-t-il une telle définition?
Regardons la CanBuildFromdéfinition de:
trait CanBuildFrom[-From, -Elem, +To] 
extends AnyRef
Il en CanBuildFromest de même de la contre-variante sur son premier paramètre de type. Parce que Nothingc'est une classe inférieure (c'est-à-dire, c'est une sous-classe de tout), cela signifie que n'importe quelle classe peut être utilisée à la place de Nothing.
Puisqu'un tel générateur existe, Scala peut l'utiliser pour produire la sortie souhaitée.
À propos des constructeurs
De nombreuses méthodes de la bibliothèque de collections de Scala consistent à prendre la collection d'origine, à la traiter d'une manière ou d'une autre (dans le cas de map, transformer chaque élément) et à stocker les résultats dans une nouvelle collection.
Pour maximiser la réutilisation du code, ce stockage des résultats se fait via un générateur ( scala.collection.mutable.Builder), qui prend essentiellement en charge deux opérations: l'ajout d'éléments et le retour de la collection résultante. Le type de cette collection résultante dépendra du type du générateur. Ainsi, un Listgénérateur renverra un List, un Mapgénérateur renverra un Map, et ainsi de suite. La mise en œuvre de la mapméthode n'a pas à se préoccuper du type de résultat: le constructeur s'en charge.
D'un autre côté, cela signifie qu'il mapfaut en quelque sorte recevoir ce constructeur. Le problème rencontré lors de la conception des collections Scala 2.8 était de savoir comment choisir le meilleur constructeur possible. Par exemple, si je devais écrire Map('a' -> 1).map(_.swap), j'aimerais récupérer Map(1 -> 'a'). En revanche, un Map('a' -> 1).map(_._1)ne peut pas retourner un Map(il renvoie un Iterable).
La magie de produire le meilleur possible à Builderpartir des types d'expression connus s'exerce à travers cet CanBuildFromimplicite.
À propos CanBuildFrom
Pour mieux expliquer ce qui se passe, je vais donner un exemple où la collection en cours de mappage est un Mapau lieu d'un List. J'y reviendrai plus Listtard. Pour l'instant, considérons ces deux expressions:
Map(1 -> "one", 2 -> "two") map Function.tupled(_ -> _.length)
Map(1 -> "one", 2 -> "two") map (_._2)
Le premier retourne un Mapet le second retourne un Iterable. La magie du retour d'une collection appropriée est l'œuvre de CanBuildFrom. Examinons mapà nouveau la définition de pour la comprendre.
La méthode mapest héritée de TraversableLike. Il est paramétré sur Bet That, et utilise les paramètres de type Aet Repr, qui paramètrent la classe. Voyons ensemble les deux définitions:
La classe TraversableLikeest définie comme:
trait TraversableLike[+A, +Repr] 
extends HasNewBuilder[A, Repr] with AnyRef
def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That 
Pour comprendre d'où Aet d' où nous Reprvenons, considérons la définition de Maplui-même:
trait Map[A, +B] 
extends Iterable[(A, B)] with Map[A, B] with MapLike[A, B, Map[A, B]]
Parce que TraversableLikeest héritée par tous les traits qui se prolongent Map, Aet Reprpourrait être hérité de l' un d'eux. Le dernier a cependant la préférence. Donc, suivant la définition de l'immuable Mapet de tous les traits qui le relient TraversableLike, nous avons:
trait Map[A, +B] 
extends Iterable[(A, B)] with Map[A, B] with MapLike[A, B, Map[A, B]]
trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] 
extends MapLike[A, B, This]
trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]] 
extends PartialFunction[A, B] with IterableLike[(A, B), This] with Subtractable[A, This]
trait IterableLike[+A, +Repr] 
extends Equals with TraversableLike[A, Repr]
trait TraversableLike[+A, +Repr] 
extends HasNewBuilder[A, Repr] with AnyRef
Si vous passez les paramètres de type Map[Int, String]tout au long de la chaîne, nous constatons que les types passés à TraversableLike, et donc utilisés par map, sont:
A = (Int,String)
Repr = Map[Int, String]
Pour revenir à l'exemple, la première carte reçoit une fonction de type ((Int, String)) => (Int, Int)et la seconde carte reçoit une fonction de type ((Int, String)) => String. J'utilise la double parenthèse pour souligner qu'il s'agit d'un tuple reçu, car c'est le type de celui Aque nous avons vu.
Avec ces informations, considérons les autres types.
map Function.tupled(_ -> _.length):
B = (Int, Int)
map (_._2):
B = String
Nous pouvons voir que le type retourné par le premier mapest Map[Int,Int], et le second est Iterable[String]. En regardant mapla définition de, il est facile de voir que ce sont les valeurs de That. Mais d'où viennent-ils?
Si nous regardons à l'intérieur des objets compagnons des classes impliquées, nous voyons quelques déclarations implicites les fournissant. Sur l'objet Map:
implicit def  canBuildFrom [A, B] : CanBuildFrom[Map, (A, B), Map[A, B]]  
Et sur objet Iterable, dont la classe est étendue par Map:
implicit def  canBuildFrom [A] : CanBuildFrom[Iterable, A, Iterable[A]]  
Ces définitions fournissent des usines pour paramétré CanBuildFrom.
Scala choisira l'implicite disponible le plus spécifique. Dans le premier cas, c'était le premier CanBuildFrom. Dans le second cas, le premier ne correspondant pas, il a choisi le second CanBuildFrom.
Retour à la question
Voyons le code de la définition de la question Listet mapde (encore) pour voir comment les types sont inférés:
val map : Map[Int,String] = List("London", "Paris").map(x => (x.length, x))(breakOut)
sealed abstract class List[+A] 
extends LinearSeq[A] with Product with GenericTraversableTemplate[A, List] with LinearSeqLike[A, List[A]]
trait LinearSeqLike[+A, +Repr <: LinearSeqLike[A, Repr]] 
extends SeqLike[A, Repr]
trait SeqLike[+A, +Repr] 
extends IterableLike[A, Repr]
trait IterableLike[+A, +Repr] 
extends Equals with TraversableLike[A, Repr]
trait TraversableLike[+A, +Repr] 
extends HasNewBuilder[A, Repr] with AnyRef
def map[B, That](f : (A) => B)(implicit bf : CanBuildFrom[Repr, B, That]) : That 
Le type de List("London", "Paris")est List[String], donc les types Aet Reprdéfinis sur TraversableLikesont:
A = String
Repr = List[String]
Le type de (x => (x.length, x))est (String) => (Int, String)donc le type de Best:
B = (Int, String)
Le dernier type inconnu Thatest le type du résultat de map, et nous l'avons déjà aussi:
val map : Map[Int,String] =
Alors,
That = Map[Int, String]
Cela signifie qu'il breakOutdoit nécessairement renvoyer un type ou un sous-type de CanBuildFrom[List[String], (Int, String), Map[Int, String]].
               
              
List, mais pourmap.