# 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`

.

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.

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 for more information.

## Using Generators

Generators can be used in `for-in`

blocks, or inside a `with`

block.

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:

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}}");
}
}

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);
}
}