Travis,
The context of my problem was to find out if one collection is a prefix of another collection. eg #(1 2) prefix: #(1 2 3) I wanted it to return false for cases like: #(1 2 3) prefix: #(1 2).
I suspect there are many cases where it would be more flexible to examine both collections until one or the other reaches its end. It's hard in this case to say what the correct behaviour is, since it depends on context and programmer intent.
I'm not sure what you are doing with the ReadStream - you can only use a ReadStream on a sequencable collection, so using this method at the base of the Collection hierachy is not going to work. (offcourse you can do something like: self asOrderedCollection readStream)
I find it frustrating that there are no external iterators for any of the unordered classes. I implemented a good workaround in Dolphin that can produce a readStream on any class that implements do: [ ..]
The trick was to embed do: [ ] into a process, held by the readStream object. This process waits on a Mutex in the readStream object, which is only signalled when the readStream receives the #next message.
ReadStream on: egDictionary | cursor mutex iterationProcess | iterationProcess := [egDictionary do: [ : each | mutex wait. cursor := each]] fork blah blah..
next
mutex signal. ^cursor.
This works with the usual proviso that you shouldn't modify a collection while iterating over it.
If anyone is interested, I could try to port this to Squeak. It would be good if readStream was a message implemented by all collections to return an external cursor on themselves.
This would lessen the needs for methods like with: do:, since it is notoriously difficult to use internal iterators to compare several collections.
Peter Smet wrote:
I notice that collection with:do: is ok if the first collection is smaller than the second collection, but fails if the first collection is the larger. Since the method is happy to run with unequal sizes one way, for the sake of consistency, it should do so the other way also.
Here is a fix:
with: otherCollection do: twoArgBlock "Evaluate twoArgBlock with corresponding elements from this collection
and
otherCollection." 1 to: (self size min: otherCollection size) do: [:index | twoArgBlock value: (self at: index) value: (otherCollection at: index)]
IMO, if the two sizes do not match, an error should be raised. I'm doubting that anyone is actually reliably relying on leveraging this (mis)feature.
with: aCollection do: aBlock | rs | aCollection size = self size ifFalse: [self error: 'Collection sizes do
not
match']. rs := ReadStream on: aCollection. self do: [:each | aBlock value: each value: rs next]
and reimplemented in SequenceableCollection as
with: aCollection do: aBlock | index | aCollection size = self size ifFalse: [self error: 'Collection sizes do
not
match']. index := 0. aCollection do: [:each | aBlock value: (self at: (index := index + 1)) value: each]
-- Travis Griggs (a.k.a. Lord of the Fries) Member, Fraven Skreiggs Software Collective Key Technology P-P-P-Penguin Power!
squeak-dev@lists.squeakfoundation.org