Skip to content
Matt Bierner edited this page Nov 8, 2015 · 32 revisions

Execution

run(g, ud, random = Math.random)

g.run(ud, random = Math.random)

Run a generator to completion, combining results into a string.

  • g - Generator to run.
  • ud - Optional, user data.
  • r - Optional, custom random number generator.
const p = pep.seq('a', pep.choice('b', 'c'));

p.run() === 'ac';
p.run() === 'ac';
p.run() === 'ab';

fold(f, z, g, ud, random = Math.random)

g.fold(f, z, ud, random = Math.random)

Left fold over a generator.

  • f - Accumulation function, passed accumulated value and current value.
  • z - Initial value.
  • g - Generator to run.
  • ud - Optional, user data.
  • r - Optional, custom random number generator.
const p = pep.seq('a', 'b', 'c');

pep.fold((p, c) => p.concat(c), [], p) === ['a', 'b', 'c'];

begin(g, ud, random = Math.random)

g.begin(ud, random = Math.random)

Begin the execution of a generator. Returns a Javascript iterator.

  • g - Generator to run.
  • ud - Optional, user data.
  • r - Optional, custom random number generator.

Values are lazily produced. Javascript iterators are stateful, so you can only iterate over the result of begin once.

const p = pep.seq('a', 'b', 'c');
for (const x of p.begin())
    console.log(x);

Value Generators

lit(x)

Yields x.

pep.lit('abc').run() === 'abc';
pep.lit(5).exec().next().value === 5;

Use lit to force a generator to yield a non string value.

// Normally, `seq` will attempt to convert `myObj` to a string.
Array.from(pep.seq('a', myObj, 'c')) === ['a', '[Object object]', 'c'];

// But `lit`forces the object to be treated as a literal value.
Array.from(pep.seq('a', pep.lit(myObj), 'c')) === ['a', myObj, 'c'];

str(x)

Yields x as a string. x is converted to a string when str is first called.

pep.str('abc').run() === 'abc';
pep.str(5).exec().next().value === '5';
pep.str({}).exec().next().value === '[Object object]';

Note that pep.str('') or pep.str() is different from pep.empty. The former yield the value '' while the latter does not yield any values.

empty

Generator that does not yield any values. This can be used with choice to add the possibility that nothing will be output.

const p = pep.seq('a', pep.empty, 'b');
Array.from(p.begin()) === ['a', 'b'];

For most cases, empty is the preferred way to indicate that no value is yielded, rather than pep.str('').

Basic Combinators

seq(...generators)

g.seq(...generators)

Run a sequence of generators from left to right.

const p = pep.seq(pep.str('a'), pep.str('bc'), pep.str('c'));
Array.from(p.begin()) === ['a', 'bc', 'd'];

Any non generator arguments are wrapped in pep.str:

gen.pep('a', pep.choice(...), 3) === pep.seq(pep.str('a'), pep.choice(...), pep.str(3))

map(g, f)

g.map(f)

Map function f over each element produced by p.

const p = pep.seq('a', 'b', 'c').map(x => x + x);

p.run() === 'aabbcc';
``

Note that `f` is run on every value produced by `g`, not on the entire result of `g`. If you need to run on the entire result of `g`, use `join` or `combine` to merge all the results into a single value first.

```js
const p = pep.join(pep.seq('a', 'b', 'c')).map(x => x + x);

p.run() === 'abcabc';
Array.from(p.begin()) === ['abc', 'abc']

chain(g, f)

g.chain(f)

For each element produced by p, run function f and then run the generator that f returns.

  • g - Generator to run.
  • f - Function that maps values to generators
const p = pep.chain(pep.seq('a', 'b', 'c'), x => pep.seq(x, x));

p.run() === 'aabbcc';
Array.from(p.begin()) === ['a', 'a', 'b', 'b', 'c', 'c']

Note how the yielded values in this case differ from map.

Like with map, if you need to run on the entire result of g, use join or combine to merge all the results into a single value first.

combine(f, z, ...generators)

g.combine(f, z, ...generators)

Left fold over the results of generators, combining the results with f. Yields only a single value.

  • g - Generator to run.
  • f - Function that maps values to generators
const p = pep.combine(
    (p, c) => [p, c],
    'x',
    pep.seq('a', pep.seq('b', 'c'), 'd'));

Array.from(p.begin()) === [[[[['x', 'a'], 'b'], 'c'], 'd']]

join(f, z, ...generators)

g.join(f, z, ...generators)

Combining all results of generators into a single string value.

const p = pep.join('a', pep.seq('b', 'c'), 'd');

Array.from(p.begin()) === ['abcd']

Choice

choice(...generators)

Randomly choose from along one or more generators. Each element has the same weight.

const p = pep.choice('a', 'b', c);

p.run() === 'c';
p.run() === 'a';
p.run() === 'c';
p.run() === 'b';

Use empty to indicate the generator may choose to produce no value.

weightedChoice(weightMap)

Randomly choose from along one or more generators, each with its own relative weight.

// Produce 'b' 70% of the time, 'a' 10% and 'c' 20%.
const p = weightedChoice([
    [0.1, 'a'],
    [0.7, 'b'],
    [0.2, 'c']);

p.run() === 'b';
p.run() === 'b';
p.run() === 'c';
p.run() === 'b';

Use empty to indicate the generator may choose to produce no value.

opt(g, prob = 0.5)

Mark a value as optional. Produce g prob * 100% of the time and nothing (1 - prob) * 100% of the time

const p = pep.opt('a');

p.run() === '';
p.run() === 'a';
p.run() === 'a';

Iteration

State Interaction

Clone this wiki locally