package php.runtime.util.generator; /** * This class implements something akin to Python's "Generators". * * <p>A Generator is a function which returns an iterator. It looks like a normal * function except that it contains yield statements for producing a series a * values usable in a for-loop or that can be retrieved one at a time with the * next() function. Each "yield" temporarily suspends processing, remembering the * location execution state (including local variables and pending try-statements). * When the generator resumes, it picks-up where it left-off (in contrast to functions * which start fresh on every invocation).</p> * * @author dom */ public abstract class Generator<T> implements Iterable<T> { private ResultHandler<T> resultHandler; /** * Yield a single result. To be called from within your "run" method. * * @param t */ public final T yield(final T t) { try { return resultHandler.handleResult(t); } catch (CollectionAbortedException ex) { // suppress return null; } } public final T yield() { return yield(null); } /** * The method that will generate your results. Call yield() in here. */ protected abstract void run(YieldAdapterIterator<T> yieldAdapter); @Override public final YieldAdapterIterator<T> iterator() { final ThreadedYieldAdapter<T> yieldAdapter = new ThreadedYieldAdapter<T>(); Collector<T> collector = new Collector<T>() { protected YieldAdapterIterator iterator; @Override public void collect(final ResultHandler<T> handler) throws CollectionAbortedException { resultHandler = handler; run(iterator); } public void setIterator(YieldAdapterIterator iterator) { this.iterator = iterator; } }; YieldAdapterIterator<T> iterator = yieldAdapter.adapt(collector).iterator(); collector.setIterator(iterator); return iterator; } }