I am interested in creating my own Stream subclass and I'm wondering what methods I should override (deploying on pharo and Gemstone). I have a collection with various types of things in it and I want to be able to stream over a subset of it, containing elements of a class. I don't want to copy the collection or use a collect: block because the collection may be large. My first use case is something like this:
stream := self mailBox streamOf: QTurnMessage.
stream size > 1
ifTrue: [ ^ stream at: 2 ]
ifFalse: [ ^ nil ]
Any pointers on what methods to override?
I needed to override
next
andatEnd
. MyStream
subclass takes a block and a collection, and iterates over all elements of the collection for whichblock
evaluates to true.Example usage:
Here is the core of it:
In Smalltalk, when we say
Stream
we refer to objects that respond to a basic protocol given by some few methods such as #next, #nextPut:, #contents, etc. So, before going into further detail I would say thatstream at: 2
, as you put in your example, is not a very appropriate expression. More appropriate expressions for aStream
would beSo, the first thing you have to consider is whether you are looking for a
Stream
or aCollection
. This basic decision depends on the behavior your objects will have to implement.Use a subclass of
Stream
in case you decide that you want to enumerate the elements using #next, i.e. mostly in sequential order. However, if you want to access your elements viaat: index
, model your objects with a subclass ofSequenceableCollection.
In case you choose streams, you will have to decide whether you will be only accessing them for reading operations or will also want to modify their contents. Your description of the problem seems to indicate that you will just read them. Therefore the basic protocol you have to implement first is
Also, if your streams will be read only, make your class a subclass of
ReadStream
.There are some few other additional messages you will have to implement if you want to inherit fancier methods. An example would be
#next:
which retrives a subcollection of several consecutive elements (its size being given by the argument.)If you instead think that it would be better to model your objects as collections, then the basic protocol you will have to implement consists of the following three methods
(I don't think your collections have to support
at:put:.
)Very recently we had the same problem you are describing and decided to model our objects as collections (rather than streams.) However, regardless of which approach you will finally follow I think that you should try both and see which one is better. Nobody will give you better advice than your Smalltalk system.
Incidentally, note also that if you have a (sequenceable)
Collection
, you will get aStream
for free: just send#readStream
to your collection!