27 · Biblioteca Estándar
Iteradores (std::Iter)
Secuencias perezosas: range, map, filter, fold, take, skip, zip, collect y each.
En esta página
std::Iter proporciona pipelines perezosos — cada paso solo procesa un
elemento cuando el siguiente paso lo solicita. No se asigna ningún array
intermedio hasta que llamas a collect() o each().
Valores opcionales y el final de la iteración
Iter.from(array), map, filter y collect conservan los elementos opcionales.
Un callback que devuelve nil en map produce un elemento presente; no
termina el pipeline. Un bucle for visita ese elemento y continúa con el siguiente.
Iter.from_fn(callback) conserva su contrato de terminación: nil devuelto
por el callback de origen termina la secuencia. La misma convención se aplica
al método next() legado de un iterador personalizado. Para procesar valores
ausentes, parte de un array o prodúcelos en un map después del origen.
Range
Iter::range(inicio, fin) produce los enteros [inicio, fin) sin
materializar el array. Es la fuente más común de un pipeline:
Secuencia numérica con extremo exclusivo; collect() materializa el array.
// Feature: Iter.range — lazy numeric sequence
// When to use: producing a source for a pipeline without materializing an array.
use std::Iter
// Simple range 0..5 (end exclusive).
let r = Iter::range(0, 5)
print(r.collect())
// expected: [0, 1, 2, 3, 4]
// Empty range when start >= end.
let empty = Iter::range(5, 5)
print(empty.collect())
// expected: []
// Sum from 1 to 10.
let sum = Iter::range(1, 11).fold(0, |acc, x| acc + x)
print(sum)
// expected: 55
// Range feeding map.
let squares = Iter::range(1, 6).map(|x| x * x).collect()
print(squares)
// expected: [1, 4, 9, 16, 25]
Map y Filter
map transforma cada elemento; filter descarta los que no cumplen el
predicado. Encadenados forman un pipeline de lectura lineal:
filter -> map -> collect sin arrays intermedios.
// Feature: Iter.map / Iter.filter — lazy transform and filter
// When to use: processing pipelines without allocating intermediate arrays.
use std::Iter
// map — transforms each item.
let doubled = Iter::range(1, 6).map(|x| x * 2).collect()
print(doubled)
// expected: [2, 4, 6, 8, 10]
// filter — keeps items that pass the predicate.
let evens = Iter::range(1, 11).filter(|x| x % 2 == 0).collect()
print(evens)
// expected: [2, 4, 6, 8, 10]
// Pipeline: filter -> map -> collect.
let it = Iter::range(1, 11)
let only_even = it.filter(|x| x % 2 == 0)
let squared = only_even.map(|x| x * x)
print(squared.collect())
// expected: [4, 16, 36, 64, 100]
Fold
fold(acc, |acc, x| ...) reduce toda la secuencia a un único valor — suma,
producto, cadena concatenada:
Suma, factorial y suma de cuadrados pares con el mismo combinador.
// Feature: Iter.fold — reduce an iterator to a single value
// When to use: summing, multiplying, building a final string, counting.
use std::Iter
// Sum 1..10.
let sum = Iter::range(1, 11).fold(0, |acc, x| acc + x)
print(sum) // expected: 55
// Product 1..6 (= 5!).
let fact = Iter::range(1, 6).fold(1, |acc, x| acc * x)
print(fact) // expected: 120
// Sum of even squares from 1..10.
let it = Iter::range(1, 11)
let it2 = it.map(|x| x * x)
let it3 = it2.filter(|x| x % 2 == 0)
let result = it3.fold(0, |acc, x| acc + x)
print(result) // expected: 220
// String concatenation.
let nums = Iter::range(1, 4)
let joined = nums.fold("", |acc, x| acc + "{x};")
print(joined)
// expected: 1;2;3;
Take y Skip
take(n) limita cuántos elementos avanzan; skip(n) ignora los primeros.
Juntos implementan paginación en cualquier iterador:
skip(1).take(3) — omite la cabecera y toma las tres líneas siguientes.
// Feature: Iter.take / Iter.skip — limit and skip elements
// When to use: pagination, taking first N, ignoring a stream header.
use std::Iter
// take — grabs the first N.
let first3 = Iter::range(0, 100).take(3).collect()
print(first3)
// expected: [0, 1, 2]
// skip — drops the first N.
let skip5 = Iter::range(0, 20).skip(5).take(4).collect()
print(skip5)
// expected: [5, 6, 7, 8]
// take beyond the length — stops at the end.
let small = Iter::range(0, 3).take(100).collect()
print(small)
// expected: [0, 1, 2]
// Skip the header of a "stream" (range simulating lines).
let lines = Iter::range(1, 11) // 10 items
let body = lines.skip(1) // ignore the "header"
let preview = body.take(3)
print(preview.collect())
// expected: [2, 3, 4]
Zip
zip combina dos iteradores en pares [a, b], deteniéndose en el más corto:
Pares de valores y mapeo de sumas con zip -> map.
// Feature: Iter.zip — combines two iterators into pairs
// When to use: pairing index/value, headers with columns, etc.
use std::Iter
// Simple zip — stops at the shorter side.
let a = Iter::range(1, 4)
let b = Iter::range(10, 14)
let pairs = a.zip(b).collect()
// Each pair is an [x, y] array.
print(pairs.len()) // expected: 3
print(pairs[0]) // expected: [1, 10]
print(pairs[1]) // expected: [2, 11]
print(pairs[2]) // expected: [3, 12]
// Zip stops at the shorter side — 3 items, not 5.
let short = Iter::range(0, 3)
let long = Iter::range(0, 5)
print(short.zip(long).collect().len())
// expected: 3
// Combine with map to sum pairs.
let xs = Iter::range(1, 5)
let ys = Iter::range(10, 14)
let zipped = xs.zip(ys)
let sums = zipped.map(|p| p[0] + p[1])
print(sums.collect())
// expected: [11, 13, 15, 17]
Collect y Each
collect() termina el pipeline y devuelve un array. each() ejecuta un
efecto secundario por elemento y retorna nil — útil para imprimir o acumular
en una variable externa:
collect devuelve un array; each es para efectos — no retorna valor.
// Feature: Iter.collect / Iter.each — terminate a pipeline
// When to use: collect when you need the array; each for side effects.
use std::Iter
// collect — materializes the iterator into an array.
let arr = Iter::range(1, 5).collect()
print(arr)
// expected: [1, 2, 3, 4]
print(arr.len()) // expected: 4
// each — runs a side effect per item, returns nil.
print("--- each ---")
Iter::range(1, 4).each(|x| print("item={x}"))
// expected: --- each ---
// expected: item=1
// expected: item=2
// expected: item=3
// Full pipeline: range -> filter -> map -> collect.
let it1 = Iter::range(1, 11)
let it2 = it1.filter(|x| x % 2 == 1) // odd numbers
let it3 = it2.map(|x| x * 10)
print(it3.collect())
// expected: [10, 30, 50, 70, 90]
Comportamiento entre backends
El backend wasm-aot todavía evalúa inmediatamente los pipelines de Iter.from
basados en arrays. Las posiciones opcionales también se conservan en ese caso.
Los pipelines de from_fn soportan map, filter, collect y for; los
adaptadores no soportados para ese origen fallan explícitamente. La paridad
completa de iteradores perezosos sigue siendo un trabajo separado.
Desafío
Construye un pipeline que produzca los primeros 5 números impares mayores que
10 usando range, filter, take y collect. ¿Cuántas llamadas a filter
se ejecutan?
Consulta también