Saltar al contenido

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.

01-range.zolo
Playground
// 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.

02-map-filter.zolo
Playground
// 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.

03-fold.zolo
Playground
// 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.

04-take-skip.zolo
Playground
// 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.

05-zip.zolo
Playground
// 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.

06-collect-each.zolo
Playground
// 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

Índice global

Encuentra tu camino por Zolo

Prueba una idea

Empieza aquí

9 resultados

9 resultados

enespt-br