Skip to content
Matt Bierner edited this page Sep 11, 2018 · 9 revisions

Apep supports using two types of variables in generators: global variables that are valid the entire scope of a program and closure variables that are scoped to a single generator.

Globals

Apep maintains a set of global variables that can be accessed at any point during generator execution using get, set, and modify. There variables are scoped to the entire execution of the generator, but reset for each generator run. The variable storage map is immutable but the stored values do not necessarily have to be.

const names = pep.choice('Alice', 'Dave');

// Get or compute the current name 
const getName = pep.get('name').map(x =>
    x === undefined
        ? names.chain(name => pep.seq(pep.set('name', name), pep.lit(name)))
        : pep.lit(x));

// ensure the same name is used in both cases
const p = pep.seq(
    'Affirmative, ', getName '. I read you. ',
    'Im sorry, ', getName, ". Im afraid I cant do that.");

p.run() === "Affirmative, Alice. I read you. Im sorry Alice. Im afraid I cant do that."
p.run() === "Affirmative, Dave. I read you. Im sorry Dave. Im afraid I cant do that."

Setting initial vars

The specifics of how Apep stores variables in left undefined, only get, set, and modify are guaranteed to work. So to set the value of variables before a generator is run, you must use these calls:

const setInitialState = (g) =>
    pep.seq(
        pep.set('a', ...),
        pep.set('b', ...),
        ...,
        g);

Because set does not yield any values, the program will only produce values from g.

Closure Variables

A second approach is to use declare to create a closure with custom state:

const counter = pep.declare(() => {
    // declare some variables local to this block.
    let sum = 0;

    return pep.seq(
        pep.seq(pep.lit(1), pep.lit(2), pep.lit(3))
            .map(x => {
                // Update the state in an expression.
                sum += i;
                return x;
            }),
        // and use the state sometime later.
        // Declare is used to make sure the current value of `i` is
        // always returned.
        pep.declare(() => gen.lit(i)));
});

Because of how declare is specified, a new closure will be generated for each invocation of counter but all sub generators returned from counter will see the closure value of sum from when they were created.

Unlike the global variables, this closure state cannot leak outside of the single generator.

Clone this wiki locally