# Generators
Generators return a series of values, one at a time.
## Generator Functions
Generator functions are defined almost exactly like functions, except that
their type is `gen` instead of `fn`.
```ki
gen single_evens(): (int) {
var x: 2
while (x <= 8) {
yield x
x += 2
}
}
gen single_evens_reversed(): (int) {
var x: 8
while (x >= 2) {
yield x
x -= 2
}
}
gen all_evens(): (int) {
var x: 2
yield x
x += 2
}
```
## Generator Expressions
A generator expression defines a generator in a single line.
```ki
fn main() {
val single_evens: (n for n in [1..9] if n % 2 == 0)
val single_evens_backwards: (n for n in [9..1, -1] if n % 2 == 0)
val all_evens: (n for n in [1..] if n % 2 == 0)
}
```
Note also the range expressions `[1..9]`, `[9..1, -1]`, and `[1..]`. See
[ranges](ki_ranges.html) for more information.
## Using Generators
Generators can be used in `for-in` blocks, or inside a `with` block.
```ki
fn main() {
val single_evens: (n for n in [1..9] if n % 2 == 0)
val single_evens_backwards: (n for n in [9..1, -1] if n % 2 == 0)
val all_evens: (n for n in [1..] if n % 2 == 0)
with (single_evens.next() as single_even) {
echo("First single even: ${single_even}")
}
for (single_even in single_evens) {
echo("Next single even: ${single_even}")
}
echo("No more single evens!")
}
```
This restriction is necessary as generators may stop yielding values at any
time, and outside a `with` or `for-in` block, the variable would potentially be
left uninitialized.
## Performance Considerations
Generators are **much** slower than static sequences like arrays; laziness is
the main reason to use them. The canonical example is a Fibonacci sequence:
rather than computing each Fibonacci number and storing the result in a large
array, you can generate each successive value as you need it.
---
## Generators vs. Coroutines
I think getting rid of `gen` in favor of `coro` is a lot better. You pretty
much have to implement coroutines to have generators anyway, so it's fine.
FWIW, the implementation is:
```ki
gen fib() (uint) {
var number3: 0
var number2: 1
var number1: 0
number1 = number2 + number3
yield(number1)
number3 = number2
number2 = number1
}
fn main() {
var fib_gen: fib()
for (fibn in fib_gen) {
echo("Fib: {{fibn}}");
}
}
```
```c
typedef void(fib_gen_func_type)(fib_gen_context *context, uint *out, Error *e);
typedef struct {
bool _finished;
uint number3
uint number2
uint number1
fib_gen_func_type next;
} fib_gen_context;
void fib_gen_func(fib_gen_context *context, uint *out, Error *e) {
context->number1 = context->number2 + context->number3;
*out = context->current_number;
context->number3 = context->number2
context->number2 = context->number1
}
void init_fib_gen_context(fib_gen_context *context) {
context->_finished = false;
context->number3 = 0;
context->number2 = 1;
context->number1 = 0;
context->next = fib_gen_func;
}
int main(void) {
fib_gen_context fib_gen;
init_fib_gen_context(&fib_gen);
while (!fib_gen.finished) {
Error e;
uint next_fib_number;
fib_gen.next(&fib_gen, &next_fib_number, &e);
if (e.occurred) {
handle_error(&e);
}
printf("Fib: %d\n", next_fib_number);
}
}
```