Generators
Generators are pure, pull-based sequence producers. They are distinct from effects: a generate { ... } block is purely functional and cannot perform I/O.
They:
- do not perform effects
- do not suspend execution stacks
- model finite or infinite data
7.1 Generator type
Generator A7.2 Generator expressions
gen = generate {
yield 1
yield 2
yield 3
}From Python/JavaScript
Similar to yield syntax, but purely functional (no mutable iterator state).
From Haskell/Scala (no list comprehension syntax)
AIVI does not use Haskell-style list comprehensions like:
// Not AIVI syntax
[ x | x <- xs, p x ]Instead, write the equivalent logic with a generate block:
generate {
x <- xs
x -> p x
yield x
}7.3 Guards and predicates
Generators use a Scala/Haskell-style binder:
x <- xsbindsxto each element produced byxsx = eis a plain (pure) local bindingx -> predis a guard (filtersx); multiple guards may appear
In a guard, pred is a predicate expression with the implicit _ bound to x (so bare fields like active resolve to x.active).
This means these are equivalent:
u -> isValidEmail email
u -> isValidEmail (_.email)
u -> isValidEmail u.emailNote: .email is an accessor function (x => x.email). It’s useful for map .email, but in a predicate position you usually want a value like email / _.email, not a function.
generate {
x <- xs
x -> price > 80
yield x
}Predicate rules are identical to filter.
7.4 Effectful streaming (future direction)
The v0.1 surface syntax does not include generate async.
The recommended model is:
- keep
Generatorpure, and - represent async / I/O-backed streams as an
Effectthat produces a generator, or via a dedicatedStreamtype in the standard library.
This aligns with the general design principle: generators stay pure; use Effect for async pull.
7.5 Expressive Sequence Logic
Generators provide a powerful, declarative way to build complex sequences without intermediate collections or mutation.
Cartesian Products
// Generate all pairs in a grid
grid = generate {
x <- [0..width]
y <- [0..height]
yield (x, y)
}Complex Filtering and Transformation
// Find active premium users with valid emails
processed = generate {
u <- users
u -> active && tier == Premium && isValidEmail email
yield { name: u.name, email: toLower u.email }
}Expressive Infinity
// Infinite sequence of Fibonacci numbers
fibs = generate {
loop (a, b) = (0, 1) => {
yield a
recurse (b, a + b)
}
}loop (pat) = init => { ... } introduces a local tail-recursive loop for generators. Inside the loop body, recurse next continues with the next state.