<> <> <> Generator: CEDAR DEFINITIONS = BEGIN <> Handle: TYPE = REF HandleRecord; HandleRecord: TYPE = RECORD[ clientData: REF ANY, private: REF HandlePrivateRecord]; HandlePrivateRecord: TYPE; <> CreateGenerator: PROC[enumerator: PROC[self: Handle], clientData: REF ANY _ NIL] RETURNS[generator: Handle]; <> ReStart: PROC [self: Handle]; <> Generate: PROC [self: Handle] RETURNS [next: REF ANY]; <> Terminate: PROC [self: Handle]; <> Produce: PROC [self: Handle, next: REF ANY] RETURNS[done: BOOLEAN]; <> END. For example, Atom.MapAtoms is a procedure which maps through all of the atoms in the world applying a given procedure to each one. To create a generator which will upon successive calls to Generate produce all of the atoms in the world, we simply construct a procedure of type PROC [self: Handle] which calls MapAtoms with an appropriate procedureal argument, namely one that uses Produce to return successive atoms, and terminates the MapAtoms if the call to Produce returns TRUE: AtomEnumerator: PROC [self: Handle] = { proc: PROC [atom: ATOM] = {IF Produce[self, atom] THEN ERROR Done}; -- the procedural argument to be given to MapAtoms. Done: ERROR = CODE; Atom.MapAtoms[proc ! Done => CONTINUE]; }; Then we simply call CreateGenerator on this enumeratr:: gen: Handle _ CreateGenerator[Enumerator]; Calling Generate[gen] will return successive atoms. Terminate[gen] will stop the enumerator.