[BUG] collection with: do: on uneven sizes problem...

Peter Smet peter.smet at flinders.edu.au
Sat May 29 13:16:16 UTC 1999


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.

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
>> 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
>    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
>    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!

More information about the Squeak-dev mailing list