comparing Sequenceable Collections.

Jarvis, Robert P. Jarvisb at timken.com
Fri Jul 2 12:59:40 UTC 1999


(My initial reply to Peter's note went directly to him instead of to the
list, so I'm redirecting this so as to get everyone involved).

I was rather surprised to find that #= was used when removing elements from
a collection.  I'm guessing that the culprit is
#OrderedCollection>>remove:ifAbsent, which currently looks like

	remove: oldObject ifAbsent: absentBlock
		| index |
		index _ firstIndex.
		[index <= lastIndex]
			whileTrue: 
				[oldObject = (array at: index)
					ifTrue: 
						[self removeIndex: index.
						^ oldObject]
					ifFalse: [index _ index + 1]].
		^ absentBlock value

It looked to me like the #= send in the sixth line could be replaced by #==
without compromising the intent of the method, but after a bit of
experimenting I found this wasn't a good idea.  Consider if you're storing
strings in a collection:

	| col |
	col := OrderedCollection new.
	1 to: 10 do: [ :i | col add: i printString ].
	Transcript show: col printString.

OK, now we've got strings '1' '2'...'10' stored in the collection.  If you
replace the #= in OrderedCollection>>remove:ifAbsent: with #== and accept
the change, then try the following

	col remove: '1' ifAbsent: [ Transcript show: 'Couldn''t find it' ]

you get the message

	Couldn't find it

displayed on the Transcript.  This is because different strings with the
same contents are not the identical object, so the comparison in question
fails and the object is never removed from the collection.  So it looks like
the proper way to compare objects in OrderedCollection>>remove:ifAbsent: is
with the #= message, if you're planning on storing non-identity objects in
it.

Maybe you could subclass OrderedCollection to get the behavior you want,
e.g. create a DictionaryCollection class which reimplements remove:ifAbsent
using #== instead of #= as the comparison method.  This may be something of
a heavyweight solution, and is perhaps more trouble than it's worth, so your
solution of generating a new collection may be your best option.

Also, you might consider rewriting your fragment as

	collection := collection reject: [ :each | each == aDictionary ]

as it seems to be a bit clearer about what's going on.

Bob Jarvis
The Timken Company

> -----Original Message-----
> From:	Peter Novak [SMTP:pno at whitestein.com]
> Sent:	Friday, July 02, 1999 9:04 AM
> To:	Jarvis, Robert P.
> Subject:	Re: comparing Sequenceable Collections.
> 
> Hi. Now it's okay, but it seems to me not very practical to use
> solution like is mine.
> 
> I had few OrderedCollections and it's elements were big Dictionaries
> (like Smalltalk). I tought that the easiest way to to remove some element
> from
> those OrderedCollections is
> 
> colection remove: aDictionary ifAbsent: [Object inform: 'nothing'].
> 
> but when the thing I wanted to remove was Smalltalk Dictionary it took
> the Squeak too much time (because of using message = somwhere deeper in
> the
> system). So I think that in todays state it's impossible (in
> normal time) to remove large dicionaries (or large collections) from
> another large collections. My solution was:
> 
> collection := (collection select: [:each | (each == aDictionary) not].
> 
> but it seems to me little bit unpractical.
> 
> nowo.
> 
> p.s.
> I'm a Squeak newbie and after I saw that thing are really practical in
> Squeak,
> such abnormality can suprise me a lot. ;>>>
> 
> 
> 
> -----Original Message-----
> From: Jarvis, Robert P. <Jarvisb at timken.com>
> To: 'Peter Novak' <pno at whitestein.com>
> Date: 2. j™l 1999 13:05
> Subject: RE: comparing Sequenceable Collections.
> 
> 
> >Do you need to compare all the values, or just make sure they're the same
> >object?  If the latter, try
> >
> > Smalltalk == Smalltalk
> >
> >Bob Jarvis
> >The Timken Company
> >
> >> -----Original Message-----
> >> From: Peter Novak [SMTP:pno at whitestein.com]
> >> Sent: Friday, July 02, 1999 6:38 AM
> >> To: squeak
> >> Subject: comparing Sequenceable Collections.
> >>
> >> Hi,
> >> I have problem with comparing SequenceableCollections. I needed to
> >> evaluate
> >> something like
> >> Smalltalk = Smalltalk.
> >> After I tried to evaluate it, I waited for 2 minutes and it did
> nothing.
> >> It's too slow for
> >> normal using. Isn't it bad?
> >>
> >> peter.
> >>
> >>  << File: Peter Novak.vcf >>
> > << File: Peter Novak.vcf >> 





More information about the Squeak-dev mailing list