2010-07-27 4 views
2

La section de spécification de langage Scala 6,19 dit:Scala pour compréhensions et carte partielle

A pour la compréhension for (p <- e) yield e0 est traduit à e.map { case p => e0 }

Alors ...

scala> val l : List[Either[String, Int]] = List(Left("Bad"), Right(1)) 
l: List[Either[String,Int]] = List(Left(Bad), Right(1)) 

scala> for (Left(x) <- l) yield x 
res5: List[String] = List(Bad) 

Jusqu'ici tout va bien:

scala> l.map { case Left(x) => x } 
<console>:13: warning: match is not exhaustive! 
missing combination   Right 

     l.map { case Left(x) => x } 
      ^
scala.MatchError: Right(1) 
    at $anonfun$1.apply(<console>:13) 
    at ... 

Pourquoi la deuxième version ne fonctionne-t-elle pas? Ou plutôt, pourquoi la première version fonctionne-t-elle?

+1

en utilisant l.collect {case Left (x) => x} à la place. – Eastsun

Répondre

4

Si vous utilisez la recherche de motifs dans votre for -comprehension le compilateur fait insérer un appel à filter avec un instanceOf -check avant d'appliquer la map.

EDIT:

également dans la section 6,19 il dit:

Un générateur p < - e suivi d'un garde si g est traduit en un seul générateur p < - e.withFilter ((x1, ..., xn) => g) où x1, ..., xn sont les variables libres de p.

Un générateur est défini plus tôt comme:

Générateur :: = Pattern1 '< -' Expr [garde]

Lors de l'inspection du bytecode, vous verrez l'appel à filter précédant l'appel au map.

+1

Pouvez-vous pointer vers le morceau de la spécification qui en parle? Je pensais que le 'filtre' ne s'appliquait qu'aux ** gardes **: c'est-à-dire' pour (e <- si cond) ' –

+2

6.19 Pour les Compréhensions et les Boucles Le schéma de traduction est le suivant. Dans un premier temps, chaque générateur p true; case _ => false} Ensuite, les règles suivantes sont appliquées de manière répétée jusqu'à ce que toutes les compressions aient été éliminées . • A pour la compréhension de (p e0}. – Eastsun

1

Spécification de langage Scala 2.7, page 83, deuxième paragraphe à partir du bas (ne pas avoir les spécifications 2.8 ici). L'insertion de filtres pour l'appariement de motifs de générateur est la première étape du processus de traduction pour la compréhension. Un problème, la dernière fois que j'ai vérifié, cela ne fonctionne pas pour les modèles typés, ce qui peut être surprenant. Donc, dans votre exemple

for(x:Left <- l) yield x 

ne fonctionnerait pas, lancer une erreur de type

+0

Il peut par tricked: val as = Seq ("a", 1, true,()); pour (a @ (dummy: Boolean) <- as) donner un – retronym

2

En complément aux remarques de Eastsun: Scala 2.8 a une méthode de recueillir, qui travaillerait dans votre exemple:

l.collect { case Left(x) => x } 
//--> List[String] = List(Bad) 
+0

j'ai eu recours à for-compris dans l'étape 1, puis une collecte distincte sur le résultat de la compréhension à l'étape 2. est-il possible de "recueillir" dans une compréhension pour éviter d'avoir à avoir deux "étapes"? –

Questions connexes