sclass PStack is Steppable { settable new ProbabilisticScheduler scheduler; sclass NoOptionsException extends RuntimeException {} srecord noeq ExecuteOption(IVF1 option) is VStack.Computable { public void step(VStack stack, O subComputationResult) { O target = stack.caller(); stack.return(); option.get(target); } } class SingleStack extends VStack is IPStack, Runnable { double probability = 1.0; *() {} *(PStackComputable computable) { super(computable); } run { print("Stepping " + last(stack)); if (step()) { print("Re-scheduling myself at " + probability); // re-add myself to scheduler to continue scheduler.add(probability, this); } } public void options(B function, Iterable> options) { L> optionsList = nonNulls(options); if (empty(optionsList)) throw new NoOptionsException; // probability penalty according to number of options probability = probability/l(optionsList); // Schedule all options except first in cloned stacks for (int i = 1; i < l(optionsList); i++) { new SingleStack s; s.stack = shallowCloneElements(stack); s.push(new ExecuteOption(optionsList.get(i))); s.probability = probability; scheduler.at(probability, s); } // First option is executed in same stack push(new ExecuteOption(first(optionsList)); } } srecord noeq FollowUp(PStackComputable computable, IVF1 onCompletion) extends PStackComputableWithStep { // !customConstructor *(PStackComputable *computable, IVF1 *onCompletion) { probability = computable.probability; } void step(IPStack stack) { if (step == 0) { stack.push(computable); ++step; } else { onCompletion.get((A) stack.subResult()); stack.return(); } } } void add(PStackComputable computable) { scheduler.at(computable.probability, new SingleStack(computable)); } void add(PStackComputable computable, IVF1 onCompletion) { if (onCompletion != null) add(new FollowUp<>(computable, onCompletion)); else add(computable); } public bool step() { ret scheduler.step(); } }