Combining Iterators
zip combines two iterators into [a, b] pairs, stopping at the shorter one. It is useful
for processing parallel series — names with ages, indices with values, etc.
chain concatenates them in sequence, without creating an intermediate array:
zip with equal and different lengths; chain of ranges and prefix/suffix.
07-iter-zip-chain.zolo
// Feature: `Iter.zip` and `Iter.chain`
// Syntax: `a.zip(b)` pairs them; `a.chain(b)` concatenates.
// When to use: combine two parallel series (zip) or stitch two
// sequences into one (chain).
use std::Iter
// zip — stops at the shorter one.
let names = Iter::from(["Alice", "Bob", "Charlie"])
let ages = Iter::from([30, 25, 35])
let pairs = names.zip(ages)
print(pairs.collect())
// expected: [["Alice", 30], ["Bob", 25], ["Charlie", 35]]
// zip with different sizes — output has the size of the shorter one.
let a = Iter::from([1, 2, 3, 4, 5])
let b = Iter::from(["x", "y"])
let mixed = a.zip(b)
print(mixed.collect())
// expected: [[1, "x"], [2, "y"]]
// chain — first a, then b.
let part1 = Iter::range(1, 4)
let part2 = Iter::range(7, 10)
let combined = part1.chain(part2)
print(combined.collect())
// expected: [1, 2, 3, 7, 8, 9]
// chain is useful to insert a prefix/suffix.
let body = Iter::from([10, 20, 30])
let header = Iter::from([0])
let with_header = header.chain(body)
print(with_header.collect())
// expected: [0, 10, 20, 30]
Every lazy pipeline needs a terminal consumer to execute.
collect() materializes the result into an array; each(fn) iterates over the elements
executing only effects, without producing an array:
collect after map; each for line-by-line logging; counter via closure with each.
08-iter-collect-each.zolo
// Feature: `Iter.collect` and `Iter.each`
// Syntax: `it.collect()` materializes into an array; `it.each(fn)`
// runs an effect per element (without producing an array).
// When to use: collect when you need the result; each when you only
// want a side effect per item.
use std::Iter
// collect — produces an array.
let arr = Iter::range(1, 4).map(|x| x * 10).collect()
print(arr)
// expected: [10, 20, 30]
// each — effect only, return is nil.
print("listing:")
Iter::range(1, 4).each(|x| print(" item {x}"))
// expected:
// listing:
// item 1
// item 2
// item 3
// Combining: count how many were consumed via closure.
var count = 0
Iter::range(1, 11).filter(|x| x % 3 == 0).each(|_| {
count += 1
})
print("multiples of 3 in 1..10 = {count}")
// expected: multiples of 3 in 1..10 = 3
Remember:
Iter.*is lazy — if you do not callcollect,each, orfold, no element will be processed.
See also