Scala Language
Pour les expressions
Recherche…
Syntaxe
- for {clauses} body
- pour {clauses} Rendement
- for (clauses) body
- for (clauses) corps entier
Paramètres
Paramètre | Détails |
---|---|
pour | Mot clé requis pour utiliser une boucle / compréhension |
clauses | L'itération et les filtres sur lesquels fonctionne pour. |
rendement | Utilisez cette option si vous souhaitez créer ou «céder» une collection. Utiliser yield entraînera le type de retour du for à être une collection au lieu de Unit . |
corps | Le corps de l'expression for, exécutée à chaque itération. |
Basic For Loop
for (x <- 1 to 10)
println("Iteration number " + x)
Cela démontre l'itération d'une variable, x
, de 1
à 10
et de faire quelque chose avec cette valeur. Le type de retour de ceci for
compréhension est Unit
.
Basic For Comprehension
Cela démontre un filtre sur une boucle for, et l'utilisation de yield
pour créer une «compréhension de séquence»:
for ( x <- 1 to 10 if x % 2 == 0)
yield x
La sortie pour ceci est:
scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)
Un pour la compréhension est utile lorsque vous devez créer une nouvelle collection basée sur l'itération et ses filtres.
Imbriqué pour boucle
Cela montre comment vous pouvez parcourir plusieurs variables:
for {
x <- 1 to 2
y <- 'a' to 'd'
} println("(" + x + "," + y + ")")
(Notez que to
ici est une méthode d'opérateur infixe qui renvoie une plage inclusive . Voir la définition ici .)
Cela crée la sortie:
(1,a)
(1,b)
(1,c)
(1,d)
(2,a)
(2,b)
(2,c)
(2,d)
Notez qu'il s'agit d'une expression équivalente, utilisant des parenthèses au lieu de crochets:
for (
x <- 1 to 2
y <- 'a' to 'd'
) println("(" + x + "," + y + ")")
Afin d'obtenir toutes les combinaisons dans un seul vecteur, nous pouvons yield
le résultat et le définir sur un val
:
val a = for {
x <- 1 to 2
y <- 'a' to 'd'
} yield "(%s,%s)".format(x, y)
// a: scala.collection.immutable.IndexedSeq[String] = Vector((1,a), (1,b), (1,c), (1,d), (2,a), (2,b), (2,c), (2,d))
Monadic pour les compréhensions
Si vous avez plusieurs objets de types monadiques , nous pouvons obtenir des combinaisons de valeurs en utilisant un «pour la compréhension»:
for {
x <- Option(1)
y <- Option("b")
z <- List(3, 4)
} {
// Now we can use the x, y, z variables
println(x, y, z)
x // the last expression is *not* the output of the block in this case!
}
// This prints
// (1, "b", 3)
// (1, "b", 4)
Le type de retour de ce bloc est Unit
.
Si les objets sont du même type monadique M
(par exemple, Option
), l'utilisation de yield
retournera un objet de type M
au lieu de Unit
.
val a = for {
x <- Option(1)
y <- Option("b")
} yield {
// Now we can use the x, y variables
println(x, y)
// whatever is at the end of the block is the output
(7 * x, y)
}
// This prints:
// (1, "b")
// The val `a` is set:
// a: Option[(Int, String)] = Some((7,b))
Notez que le mot-clé de yield
ne peut pas être utilisé dans l'exemple d'origine, où il existe un mélange de types monadiques ( Option
et List
). Si vous essayez de le faire, vous obtenez une erreur d'incompatibilité de type à la compilation.
Itérer à travers des collections en utilisant une boucle For
Cela montre comment imprimer chaque élément d'une carte
val map = Map(1 -> "a", 2 -> "b")
for (number <- map) println(number) // prints (1,a), (2,b)
for ((key, value) <- map) println(value) // prints a, b
Cela montre comment imprimer chaque élément d'une liste
val list = List(1,2,3)
for(number <- list) println(number) // prints 1, 2, 3
Desugaring For Comprehensions
for
compréhension à Scala, il n'y a que du sucre syntaxique . Ces compréhensions sont implémentées à l'aide des withFilter
, foreach
, flatMap
et map
de leurs types de sujet. Pour cette raison, seuls les types pour lesquels ces méthodes sont définies peuvent être utilisés for
compréhension.
A for
compréhension de la forme suivante, avec des motifs pN
, des générateurs gN
et des conditions cN
:
for(p0 <- x0 if g0; p1 <- g1 if c1) { ??? }
... dé-sucre aux appels imbriqués en utilisant withFilter
et foreach
:
g0.withFilter({ case p0 => c0 case _ => false }).foreach({
case p0 => g1.withFilter({ case p1 => c1 case _ => false }).foreach({
case p1 => ???
})
})
Considérant une expression for
/ yield
de la forme suivante:
for(p0 <- g0 if c0; p1 <- g1 if c1) yield ???
... withFilter
les appels imbriqués en utilisant withFilter
et soit flatMap
ou map
:
g0.withFilter({ case p0 => c0 case _ => false }).flatMap({
case p0 => g1.withFilter({ case p1 => c1 case _ => false }).map({
case p1 => ???
})
})
(Notez que la map
est utilisée dans la compréhension la plus profonde, et que flatMap
est utilisé dans toute compréhension externe.)
Un for
compréhension peut être appliqué à tout type mettant en œuvre les méthodes requises par la représentation sans sucre. Il n'y a pas de restrictions sur les types de retour de ces méthodes, tant qu'elles sont composables.