(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@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@timken.com To: 'Peter Novak' pno@whitestein.com Date: 2. jl 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@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 >>
squeak-dev@lists.squeakfoundation.org