Generators & Iterators
Wyn supports generator functions using the yield keyword. Generators produce values lazily — they only compute the next value when asked.
Basic Generator
wyn
fn count(n: int) -> iter {
for i in 0..n {
yield i
}
}
fn main() {
var nums = count(5).collect()
print("${nums.len()} numbers") // 5 numbers
}A function with yield becomes a generator. It returns an iterator (iter) that produces values on demand.
Iterator Methods
Chain methods to transform iterator output:
wyn
fn range(n: int) -> iter {
for i in 0..n { yield i }
}
fn main() {
// .collect() — gather all values into an array
var all = range(5).collect() // [0, 1, 2, 3, 4]
// .map(fn) — transform each value
var doubled = range(4).map(fn(x: int) -> int { return x * 2 }).collect()
// [0, 2, 4, 6]
// .filter(fn) — keep values matching predicate
var evens = range(8).filter(fn(x: int) -> bool { return x % 2 == 0 }).collect()
// [0, 2, 4, 6]
// .take(n) — stop after n values
var first3 = range(1000).take(3).collect() // [0, 1, 2]
// Chain them
var result = range(10)
.map(fn(x: int) -> int { return x * x })
.filter(fn(x: int) -> bool { return x > 10 })
.take(3)
.collect()
// [16, 25, 36]
}For-In Loops
Iterate directly over a generator without collecting:
wyn
fn fib(count: int) -> iter {
var a = 0
var b = 1
for i in 0..count {
yield a
var tmp = a + b
a = b
b = tmp
}
}
fn main() {
for n in fib(10) {
print("${n}")
}
// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
}Multiple Yields
A generator can yield from anywhere in its body:
wyn
fn header_body_footer() -> iter {
yield 1 // header
yield 2 // body
yield 3 // footer
}How It Works
Generators compile to coroutine-based iterators. Each yield suspends the function and saves its state. The next call to the iterator resumes where it left off. This means generators can represent infinite sequences efficiently — only computing values as needed.
See Also
- Closures — related: lazy evaluation
- Spawn & Await — concurrent alternatives
- Control Flow —
for-into consume generators