Scala for Backend Engineering & Functional Programming · Lección

Plegado y reducción

foldLeft y reduce

Lección 3 de 413 pasos

Plegado y reducción 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.

Combinar elementos en uno solo

A veces necesita combinar todos los elementos de una colección en un único valor, como una suma o una concatenación. Scala proporciona fold, foldLeft, foldRight y reduce para hacerlo.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    println(nums.sum)
    println(nums.product)
  }
}

reduce: combinar sin valor inicial

reduce combina los elementos por pares mediante una función binaria. Necesita al menos un elemento; de lo contrario, lanza una excepción.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val total = nums.reduce((a, b) => a + b)
    println(total)
    val max = nums.reduce((a, b) => if (a > b) a else b)
    println(max)
  }
}

foldLeft: combinar con un valor inicial

foldLeft recibe un valor inicial, o semilla, y una función. Es seguro con colecciones vacías (devuelve la semilla) y permite que el tipo del resultado sea diferente del tipo de los elementos.

Sintaxis: xs.foldLeft(seed)((acc, x) => ...).

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val sum = nums.foldLeft(0)((acc, x) => acc + x)
    println(sum)
    val empty = List.empty[Int].foldLeft(0)(_ + _)
    println(empty)
  }
}

El patrón del acumulador

En un fold, el primer argumento es el acumulador que contiene el resultado obtenido hasta el momento, y el segundo es el elemento actual. Cada paso actualiza el acumulador.

object Main {
  def main(args: Array[String]): Unit = {
    val words = List("Scala", "is", "great")
    val sentence = words.foldLeft("")((acc, w) => acc + w + " ")
    println(sentence.trim)
  }
}

El tipo del resultado puede ser diferente

Una característica potente de foldLeft es que el tipo del acumulador puede ser diferente del de los elementos. Aquí transformamos una lista de números en un String mediante un fold.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3)
    val joined = nums.foldLeft("nums:")((acc, n) => acc + " " + n)
    println(joined)
  }
}

foldRight: desde la derecha

foldRight procesa los elementos de derecha a izquierda. El acumulador es el segundo argumento: (x, acc) => .... La dirección es importante para las operaciones no conmutativas.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val left = nums.foldLeft("")((acc, x) => acc + x)
    val right = nums.foldRight("")((x, acc) => acc + x)
    println("foldLeft:  " + left)
    println("foldRight: " + right)
  }
}

De izquierda a derecha frente a derecha a izquierda y rendimiento

foldLeft es recursivo de cola y no desborda la pila con listas grandes. foldRight puede desbordar la pila en un List con entradas muy grandes. Prefiera foldLeft, salvo que el orden exija lo contrario.

object Main {
  def main(args: Array[String]): Unit = {
    val big = (1 to 100000).toList
    val total = big.foldLeft(0L)((acc, x) => acc + x)
    println(total)
  }
}

Construir una colección con fold

Los folds son suficientemente generales como para construir colecciones. Aquí invertimos una lista anteponiendo cada elemento a una lista acumuladora.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val reversed = nums.foldLeft(List.empty[Int])((acc, x) => x :: acc)
    println(reversed)
  }
}

reduceOption para mayor seguridad

Como reduce falla con colecciones vacías, reduceOption devuelve un Option: Some(result) cuando no está vacía y None cuando está vacía.

object Main {
  def main(args: Array[String]): Unit = {
    println(List(3, 1, 4).reduceOption(_ + _))
    println(List.empty[Int].reduceOption(_ + _))
  }
}

fold: una variante simétrica

fold es como foldLeft, pero el acumulador debe ser del mismo tipo que los elementos. Se suele utilizar con colecciones paralelas.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(1, 2, 3, 4)
    val total = nums.fold(0)(_ + _)
    println(total)
  }
}

Contar con foldLeft

Los folds pueden calcular resultados más elaborados, como contar cuántos elementos cumplen una condición, todo en un solo recorrido.

object Main {
  def main(args: Array[String]): Unit = {
    val nums = List(4, 7, 2, 9, 6, 1)
    val evenCount = nums.foldLeft(0)((acc, x) => if (x % 2 == 0) acc + 1 else acc)
    println(s"even numbers: $evenCount")
  }
}

Comprobación rápida

¿Cuál es la diferencia fundamental entre reduce y foldLeft?

Resumen

Ha aprendido a plegar y reducir:

  • reduce — combina por pares, no usa valor inicial y falla si está vacío
  • reduceOption — variante segura que devuelve Option
  • foldLeft — valor inicial + acumulador, segura para la pila y con tipo de resultado flexible
  • foldRight — de derecha a izquierda; tenga cuidado con la pila en listas grandes
  • Los pliegues incluso pueden construir colecciones nuevas
Gratis para empezar

Aprende Scala con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
39
Lecciones
143

Preguntas frecuentes

¿La lección «Plegado y reducción» es gratis?

Sí — el texto completo de «Plegado y reducción» 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 «Plegado y reducción»?

foldLeft y reduce 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 «Plegado y reducción»?

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. List, Vector, Set, Map
  2. Transformaciones
  3. Plegado y reducción
  4. Agrupación y ordenamiento
← Volver a Scala for Backend Engineering & Functional Programming