-
Notifications
You must be signed in to change notification settings - Fork 5
Variables
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.
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."
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
.
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.