El vie, 27-11-2009 a las 15:22 +0100, Nicolas Cellier escribió:
2009/11/27 Diego Gomez Deck DiegoGomezDeck@consultar.com:
El vie, 27-11-2009 a las 06:15 -0600, Ralph Johnson escribió:
I think we need a common superclass for Streams and Collection named Iterable where #do: is abstract and #select:, #collect:, #reject:, #count:, #detect:, etc (and quiet a lot of the messages in enumerating category of Collection) are implemented based on #do:
Of course Stream can refine the #select:/#reject methods to answer a FilteredStream that decorates the receiver and apply the filtering on the fly. In the same way #collect: can return a TransformedStream that decorates the receiver, etc.
Since Stream can't reuse #select: and #collect: (or #count, and #detect: on an infinite stream is risky),
Stream and Collection are just the 2 refinements of Iterable that we're talking about in this thread, but there are a lot of classes that can benefit from Iterable as a super-class.
On the other side, Stream has #do: (and #atEnd/#next pair) and it's also risky for infinite streams. To push this discussion forward, Is InfiniteStream a real Stream?
they shouldn't be in the superclass. In that case, what is its purpose?
i think it is fine to give Stream the same interface as Collection. I do this, too. But they will share very little code, and so there is no need to give them a common superclass.
-Ralph Johnson
Cheers,
-- Diego
#select: and #collect: are not necessarily dangerous even on infinite stream once you see them as filters and implement them with a lazy block evaluation : Stream select: aBlock should return a SelectStream (find a better name here :). Then you would use it with #next, as any other InfiniteStream.
Sure, it was my point... The only risk with InfiniteStreams is #do:
My proposal is to create Iterable class, with default implementations of #select:, #collect:, etc all based on #do: (Just like Collection implements #size based on #do: but most collections just overwrite it with a faster version). This implementation is (at the same time) naive implementations and documentation of the expected behaviour all writren in terms of #do:.
Stream implements #select:, #collect: (and those type of messages) answering a IterableDecorator that make the selection/collection/etc in lazy way.
There are also some other useful decorators to implement: like IterableComposite (an union of several iterables that can be handled like one).
The FilterIterator/CollectorIterator can also be used to select/collect lazyly on collections.
For InfiniteStreams (Random, Fibonacci Numbers, etc) I propose to create a type of "Generators" that are "less" than a Stream and less than a Iterator (they have not concept of #atEnd, #do: doesn't make sense, etc). Anyway, I'm not sure how many InfiniteStream we have in current Squeak. I remember Random was a Stream in Smalltalk/80, but not sure the current state in Squeak.
Cheers,
-- Diego