0Pricing
Scala for Backend Engineering & Functional Programming · Lección

Varios generadores

Iteración anidada

Varios generadores es una lección gratuita de Scala for Backend Engineering & Functional Programming en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Scala for Backend Engineering & Functional Programming, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

La iteración anidada se vuelve plana

Una for-comprehension puede tener varios generadores. Cada uno es una línea con <- que itera sobre una colección. Juntos producen todas las combinaciones, como un bucle anidado expresado de forma plana.

object Main {
  def main(args: Array[String]): Unit = {
    val pairs = for {
      x <- List(1, 2)
      y <- List('a', 'b')
    } yield (x, y)
    println(pairs)
  }
}

Es un producto cartesiano

Dos generadores de tamaños m y n producen m × n resultados: el producto cartesiano completo. El primer generador es el bucle externo y el segundo, el interno.

object Main {
  def main(args: Array[String]): Unit = {
    val grid = for {
      row <- 1 to 3
      col <- 1 to 3
    } yield s"r$row-c$col"
    println(grid.mkString(", "))
  }
}

El generador interno puede depender del externo

Un generador posterior puede usar valores vinculados por generadores anteriores. Esto no es posible con un producto cartesiano simple y es una de las razones por las que las for-comprehensions son tan flexibles.

object Main {
  def main(args: Array[String]): Unit = {
    val upperTriangle = for {
      i <- 1 to 4
      j <- i to 4
    } yield (i, j)
    println(upperTriangle)
  }
}

Tres o más generadores

Puede apilar tantos generadores como quiera. Con tres generadores obtiene un bucle anidado en tres niveles, que produce tuplas o valores calculados.

object Main {
  def main(args: Array[String]): Unit = {
    val triples = for {
      a <- 1 to 2
      b <- 1 to 2
      c <- 1 to 2
    } yield (a, b, c)
    println(triples.size + " combinations")
    triples.foreach(println)
  }
}

El ejemplo pitagórico clásico

Un uso famoso es encontrar ternas pitagóricas. Iteramos sobre tres números y conservamos solo aquellos para los que a*a + b*b == c*c, combinando varios generadores con una guarda.

object Main {
  def main(args: Array[String]): Unit = {
    val triples = for {
      a <- 1 to 20
      b <- a to 20
      c <- b to 20
      if a * a + b * b == c * c
    } yield (a, b, c)
    triples.foreach(println)
  }
}

Cómo se desazucara

Varios generadores se convierten en llamadas anidadas a flatMap con un map final:

  • xs.flatMap(x => ys.flatMap(y => zs.map(z => ...)))

Cada generador adicional añade un nivel anidado más.

object Main {
  def main(args: Array[String]): Unit = {
    val sugar = for {
      x <- List(1, 2)
      y <- List(3, 4)
    } yield x * y
    val desugared = List(1, 2).flatMap(x => List(3, 4).map(y => x * y))
    println(sugar == desugared)
  }
}

Mezclar generadores y guardas

Puede intercalar generadores y guardas libremente. Una guarda colocada entre dos generadores poda los valores externos antes de que se ejecute siquiera el bucle interno.

object Main {
  def main(args: Array[String]): Unit = {
    val result = for {
      x <- 1 to 5
      if x % 2 == 1
      y <- 1 to 5
      if y > x
    } yield (x, y)
    println(result)
  }
}

Aplanar colecciones anidadas

Cuando tiene una colección de colecciones, dos generadores la aplanan de forma natural: el primero itera sobre la colección externa y el segundo sobre cada colección interna.

object Main {
  def main(args: Array[String]): Unit = {
    val matrix = List(List(1, 2), List(3, 4), List(5, 6))
    val flat = for {
      row <- matrix
      value <- row
    } yield value
    println(flat)
  }
}

Construir una cuadrícula de cadenas

Varios generadores son excelentes para generar resultados estructurados, como coordenadas o una tabla de multiplicar.

object Main {
  def main(args: Array[String]): Unit = {
    val table = for {
      i <- 1 to 3
      j <- 1 to 3
    } yield s"$i*$j=${i * j}"
    println(table.grouped(3).map(_.mkString("  ")).mkString("\n"))
  }
}

Combinar colecciones de distintos tamaños

Los generadores no tienen que tener la misma longitud. Se produce cada combinación formada por un elemento de cada uno.

object Main {
  def main(args: Array[String]): Unit = {
    val sizes = List("S", "M", "L")
    val colors = List("red", "blue")
    val products = for {
      s <- sizes
      c <- colors
    } yield s"$c-$s"
    println(products)
  }
}

El orden afecta a la secuencia de salida

Intercambiar el orden de los generadores conserva el mismo conjunto de combinaciones, pero cambia su orden, porque el último generador varía más rápidamente.

object Main {
  def main(args: Array[String]): Unit = {
    val ab = for { x <- List(1, 2); y <- List(9, 8) } yield (x, y)
    val ba = for { y <- List(9, 8); x <- List(1, 2) } yield (x, y)
    println(ab)
    println(ba)
  }
}

Comprobación rápida

¿Cuántas tuplas produce for { x <- List(1,2,3); y <- List('a','b') } yield (x, y)?

Resumen

Ha aprendido sobre varios generadores:

  • Cada línea <- añade un nivel de iteración anidada
  • En conjunto, producen el producto cartesiano
  • Los generadores internos pueden depender de los valores vinculados externamente
  • Se desazucaran en flatMap anidados y un map final
  • El orden de los generadores cambia el orden de los resultados

Preguntas frecuentes

¿La lección «Varios generadores» es gratis?

Sí — el texto completo de «Varios generadores» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Scala for Backend Engineering & Functional Programming, actualiza a CoddyKit PRO. El curso de Scala for Backend Engineering & Functional Programming incluye 4 lecciones en total.

¿Qué aprenderé en «Varios generadores»?

Iteración anidada Practicas Scala for Backend Engineering & Functional Programming con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Scala for Backend Engineering & Functional Programming?

No se requiere experiencia previa. Scala for Backend Engineering & Functional Programming en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Varios generadores»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Scala for Backend Engineering & Functional Programming?

Sí. Cada lección de Scala for Backend Engineering & Functional Programming incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Desazucarado de for
  2. Filtrado con if
  3. Varios generadores
  4. Uso con Option y Future
← Volver a Scala for Backend Engineering & Functional Programming