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.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow