Buscar..


Sintaxis

  • para {cláusulas} cuerpo
  • para {cláusulas} cuerpo de rendimiento
  • para (cláusulas) cuerpo
  • para (cláusulas) ceder cuerpo

Parámetros

Parámetro Detalles
para Palabra clave requerida para usar un bucle / comprensión
cláusulas La iteración y los filtros sobre los que trabaja el.
rendimiento Use esto si quiere crear o 'producir' una colección. El uso de yield hará que el tipo de retorno de for sea ​​una colección en lugar de Unit .
cuerpo El cuerpo de la expresión, ejecutado en cada iteración.

Basic For Loop

for (x <- 1 to 10)
  println("Iteration number " + x)

Esto demuestra la iteración de una variable, x , de 1 a 10 y hacer algo con ese valor. El tipo de retorno de este for comprensión es la Unit .

Básico Para Comprensión

Esto demuestra un filtro en un bucle for, y el uso del yield para crear una 'comprensión de secuencia':

for ( x <- 1 to 10 if x % 2 == 0)
  yield x

La salida para esto es:

scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)

Una para la comprensión es útil cuando necesita crear una nueva colección basada en la iteración y sus filtros.

Anidado para bucle

Esto muestra cómo puedes iterar sobre múltiples variables:

for {
  x <- 1 to 2
  y <- 'a' to 'd'
} println("(" + x + "," + y + ")")

(Tenga en cuenta que to aquí es un método operador infijo que devuelve un rango inclusivo . Véase la definición aquí .)

Esto crea la salida:

(1,a)
(1,b)
(1,c)
(1,d)
(2,a)
(2,b)
(2,c)
(2,d)

Tenga en cuenta que esta es una expresión equivalente, utilizando paréntesis en lugar de corchetes:

for (
  x <- 1 to 2
  y <- 'a' to 'd'
) println("(" + x + "," + y + ")")

Para obtener todas las combinaciones en un solo vector, podemos yield el resultado y establecerlo en un valor 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))

Monádico para las comprensiones.

Si tiene varios objetos de tipos monádicos , podemos lograr combinaciones de los valores utilizando un 'para comprensión':

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)

El tipo de retorno de este bloque es la Unit .

Si los objetos son del mismo tipo monádico M (p. Ej., Option ), usar el yield devolverá un objeto de tipo M lugar 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))

Tenga en cuenta que la palabra clave de yield no se puede utilizar en el ejemplo original, donde hay una combinación de tipos monádicos ( Option y List ). Tratar de hacerlo producirá un error de falta de coincidencia de tipo de tiempo de compilación.

Iterar a través de colecciones utilizando un bucle for

Esto demuestra cómo imprimir cada elemento de un mapa.

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

Esto demuestra cómo imprimir cada elemento de una lista

val list = List(1,2,3)
for(number <- list) println(number) // prints 1, 2, 3

Desugaring para comprensiones

for comprensiones en Scala solo son azúcares sintácticos . Estas comprensiones se implementan utilizando los withFilter , foreach , flatMap y map de sus tipos de materias. Por esta razón, sólo los tipos que han definido estos métodos pueden ser utilizados en una for comprensión.

A for comprensión de la siguiente forma, con patrones pN , generadores gN y condiciones cN :

for(p0 <- x0 if g0; p1 <- g1 if c1) { ??? }

... reducirá el azúcar a las llamadas anidadas con withFilter y foreach :

g0.withFilter({ case p0 => c0  case _ => false }).foreach({
  case p0 => g1.withFilter({ case p1 => c1  case _ => false }).foreach({
    case p1 => ???
  })
})

Considerando que una expresión for / yield de la siguiente forma:

for(p0 <- g0 if c0; p1 <- g1 if c1) yield ???

... reducirá el azúcar a las llamadas anidadas usando withFilter y flatMap o map :

g0.withFilter({ case p0 => c0  case _ => false }).flatMap({
  case p0 => g1.withFilter({ case p1 => c1  case _ => false }).map({
    case p1 => ???
  })
})

(Tenga en cuenta que el map se usa en la comprensión más profunda, y flatMap se usa en cada comprensión externa).

A for comprensión se puede aplicar a cualquier tipo implementando los métodos requeridos por la representación sin azúcar. No hay restricciones en los tipos de retorno de estos métodos, siempre que sean compositivos.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow