The basic image in GNU Smalltalk includes powerful extensions to the Stream hierarchy found in ANSI Smalltalk (and Smalltalk-80). In particular:
inject:into:) these are completely identical. For messages that return a new stream, such as
collect:, the blocks are evaluated lazily, as elements are requested from the stream using
For example, here is an empty generator and two infinite generators:
"Returns an empty stream" Generator on: [ :gen | ] "Return an infinite stream of 1's" Generator on: [ :gen | [ gen yield: 1 ] repeat ] "Return an infinite stream of integers counting up from 1" Generator inject: 1 into: [ :value | value + 1 ]
The block is put “on hold” and starts executing as soon as
#atEnd are sent to the generator. When the block sends
#yield: to the generator, it is again put on hold and the argument
becomes the next object in the stream.
Generators use continuations, but they shield the users from their complexity by presenting the same simple interface as streams.