[BUG]Collection>>removeAll:

goran.hultgren at bluefish.se goran.hultgren at bluefish.se
Tue Aug 27 09:32:30 UTC 2002


Hi all!

(waving a white flag hysterically) :-)

Let me first tell you that this thread has been interesting and a
learning experience in many different ways, and not all about Squeak but
also rhetorics etc. ;-)

I now have a suggestion - why don't we move over into the "do it" phase?
Could Richard, which IMHO probably is the one who has this thread mostly
covered in his head, summarize a concrete proposal of a change?

If my memory serves me we have talked about:

1. Changing the base implementation of #removeAll: so that it doesn't do
fishy stuff when being called with itself as the argument. I don't want
to argue any finer points but IMHO Richard has at least proven beyond
doubt that the current situation is simply buggy and should be fixed
*somehow*.

We have heard a range of suggestions like fixing the comment (a bit like
chickening out if you ask me), signalling an exception, fixing the
implementation using copy (always or just when reciever == argument) and
various other optimization techniques so that it also gets faster.
Richard, give us your best shot.

2. Adding a #removeAll (no argument) in Collection with a nice base
implementation and then especially adding the concrete implementation in
OrderedCollection but also others perhaps.

3. Various other ideas/suggestions. (Perhaps I should comb through this
thread to find the other good bits.)


Anyway, to get us jumpstarted, here is a summary of what *I* think:

Personally :-) it still, probably unrationally, bothers me to *always*
do a copy to avoid any plausible aliasing problems. I would think that
perhaps trapping the "self == argument" situation is enough in Squeak
today (no slices etc) so I am instead leaning over to this
implementation:

Collection>>removeAll: aCollection
	"Remove each element of aCollection from the receiver. If successful
for 
	each, answer aCollection. Otherwise create an error notification.
	ArrayedCollections cannot respond to this message."

	|aBlock|
	self isEmpty ifTrue:[^aCollection].
	self == aCollection ifTrue: [^self removeAll].
	aBlock := [self errorNotFound].
	^aCollection do: [:each |
	    self remove: each ifAbsent: aBlock]]

- I check for empty as Stephan suggested. Richard may have other
opinions but it would at least guard against rather slow removing of
large collections from empty ones.
- I don't use assert but instead "==", I am not sure why assert: would
be better... Anticipation of being able to turn them off somehow in the
future? Well. IMHO this check should NOT be turned off ever.
- I use the optimization of Richard (block created once outside of loop,
using remove:ifAbsent: instead of remove:)
- I don't copy always, instead I call #removeAll and thus handles the
case of "x removeAll: x".
- I still return aCollection so the message still does what it should (I
think).

Then I added Collection>>removeAll (Gasp! How *dares* he change the
protocol of Collection! :-) because I can't see why we shouldn't have
such a method:

Collection>>removeAll
	"Remove all elements in the receiver by simply removing them
	one by one. This base implementation uses a copy of the receiver
	in order to avoid the problem of iterating over a changing collection.
	Subclasses should typically reimplement this method to be more
efficient."
 
	|aBlock|
	aBlock := [self errorNotFound].
	self copy do: [:each |
	    self remove: each ifAbsent: aBlock]].
	^self

The idea being that this implementation is rarely used since
OrderedCollection etc would use special implementations like for
example:

OrderedCollection>>removeAll
	"Remove all elements in the receiver."

     self setCollection: ( Array new: array size )

- I "reuse" array size simply guessing that it could easily grow back to
that size. Perhaps a smaller would be better as Tim suggested.


Ok, blast away.

regards, Göran

PS. I really think we should not be so *damn afraid* of
changing/improving the base Smalltalk classes. Sure, they have stood the
test of time, but everyone makes mistakes and everything can be
improved. IMHO. DS



More information about the Squeak-dev mailing list