deferred<T> function
A generator that stands in for one not written yet.
For recursive values, which Dart's initialisation rules otherwise make impossible to write: a generator that mentions itself cannot be built in one expression. This is the two-step version -- name it, then say what it is:
final trees = deferred<Tree>();
trees.define(
oneOf(<Generator<Tree>>[
integers(min: 0, max: 100).map(Leaf.new),
tuple2(trees, trees).map((pair) => Branch(pair.$1, pair.$2)),
]),
);
Recursion terminates because the engine runs out of room for it: a case has a budget of choices, and as that budget goes the draws that decide which branch to take are pushed toward their smallest value. So the non-recursive branch has to be reachable at the smallest choice -- first in a oneOf, the null of an optional -- or the recursion has nothing to bottom out into and every case overruns.
Implementation
DeferredGenerator<T> deferred<T>() => DeferredGenerator<T>._();