Generators


Generators in Factor are lazily executed blocks of code, which emit values on request. They are designed to work very similarly to generators found in languages like Python or JavaScript. Their implementation in Factor is a simple wrapper around coroutines.

Generator words are created using GEN: or GEN::. When a generator word is called, its required inputs are consumed from the stack, and a generator object is left as output. Accordingly, the right hand side of generator word's stack effect must always be a single value. For example:

GEN: repeat-forever ( val -- gen ) [ dup yield t ] loop ; GEN:: foo ( a b c -- gen ) b yield c yield a yield ;

Inside generator words, yield and its variants can be used. These words halt execution and pass a value to the caller. When a generator object is depleted (i.e., the word is fully finished executing), a stop-generator error is thrown. This error can also be thrown manually inside a generator word to end execution early.

When a generator object is depleted, its runtime is discarded and therefore any values left on its internal stack are ignored. Generator objects can also be created directly from quotations using <generator>.

Once generator objects have been created, there are multiple words to control them.

Progressing computation:
next ( gen -- result )

?next ( gen -- val/f end? )

skip ( gen -- )

take ( gen n -- seq )

take-all ( gen -- seq )


Provide a value to generator, and progress the computation:
next* ( v gen -- result )

?next* ( v gen -- val/f end? )

skip* ( v gen -- )


Check if a generator is already exhausted:
exhausted? ( gen -- ? )


All generator words are found in the generators vocabulary.