14 — Iteration
Previous: Collections
日本語版: 14_iteration.vibe.md
Almost all iteration in vibe is one eager pass over an array. This
chapter is that pass, the |> operator that chains it, and where to
look when the thing you are iterating is not a collection you already
hold.
One pass over an array
import @vibe/builtin {
trait Iterator
}
fn main with Console {
let xs = [1, 2, 3, 4]
let evens = Iterator::filter(xs, (n) -> {
n % 2 == 0
})
let sum = Iterator::fold(xs, 0, _ + _)
let doubled = for x in xs {
x * 2
}
println("evens length = \{Array::length(evens)}")
println("sum = \{sum}")
println("doubled[3] = \{Array::get(doubled, 3)}")
}
evens length = 2
sum = 10
doubled[3] = 8
for x in xs { body } collects. When xs is an Array or another
builtin collection, the loop is an expression whose value is Array[T] —
which is why doubled can be indexed. for i, x in xs binds the index
too.
Iterator::map, Iterator::filter, and Iterator::fold are eager operations
provided by the imported trait. Array implements Iterator, and statically
known Array receivers compile to the same direct loops as the Array
specializations, without dictionary-dispatch overhead.
Piping
|> passes the value on the left as the first argument on the right,
unless a bare _ marks the slot:
import @vibe/builtin {
trait Iterator
}
fn main with Console {
let n = " vibe " |> String::trim |> String::length
let xs = [1, 2, 3]
let ys = xs |> Iterator::map(_, _ * 10)
println("trimmed length = \{n}")
println("ys[1] = \{Array::get(ys, 1)}")
}
trimmed length = 4
ys[1] = 20
xs |> Iterator::map(_, _ * 10) reads as
Iterator::map(xs, (v) -> v * 10).
The two underscores are different things: the first is the pipe slot,
the second is a section — shorthand for a lambda over that argument.
When it is not an array
There is no lazy combinator chain to assemble. An Iterator::* call and a
for are the eager layer, and they are the whole of it.
The second layer is for values that arrive over time — a stream, a
socket, a file read in pieces. There you are not holding a collection,
so you pull: an iterator whose next may suspend. Suspension rides on
the effect row rather than on a special loop keyword, which is why there
is no separate for await form. See
Concurrency.
Next: Generics, traits, and derive.