What is a generator?


A generator is a quick way to create a Stream. As you might have seen in an earlier question, streams are a powerful iteration tool that Smalltalk offers. A generator is a kind of pluggable stream, in that a user-supplied blocks defines which values are in a stream.

For example, here is an empty generator and two infinite generators:

Generator on: [ :gen | ]
Generator on: [ :gen | [ gen yield: 1 ] repeat ]
Generator inject: 1 into: [ :value | value + 1 ]

As a more concrete example, these lines process a file and create Person objects out of the file:

lines := file lines.
lines := lines select: [ :line | line ~ '^[A-Za-z]+ [0-9]+$' ].
fields := lines collect: [ :line | line subStrings ].
people := fields collect: [ :data |
            Person name: data first age: data second asInteger ].

Let's see how to rewrite them to use a single Generator instead:

Generator on: [ :gen |
    file linesDo: [ :line || data |
        line ~ '^[A-Za-z]+ [0-9]+$' ifTrue: [
            data := line subStrings.
            gen yield: (Person name: data first age: data second asInteger) ] ] ].

As you can see, #select: becomes an if-statement, and the value from the final stream is yielded to the user of the generator.

Generators use continuations, but they shield the users from their complexity by presenting the same simple interface as streams.

User login