The standard does *not* support - a removeAll: a - [was: Re: [BUG] Collection>>removeAll:]

Richard A. O'Keefe ok at cs.otago.ac.nz
Thu Sep 12 04:25:04 UTC 2002


"Lex Spoon" <lex at cc.gatech.edu> wrote:
	"Richard A. O'Keefe" <ok at cs.otago.ac.nz> wrote:
	[... inline the assertions, too ...]
	
	That's an interesting way to look at the situation, but do note that
	most Smalltalkers will be suprised to find those assertions or
	corrections in removeAll:.  Most fooAll: methods just do: on the
	argument and foo: each element, and have no particular protection
	against #foo: modifying the argument.
	
What other fooAll: methods do or don't do really isn't relevant
to the question of whether #removeAll: *SHOULD* have an assertion.
My point is that you cannot present a transformation step that
*discards* the assertion (and thereby introduces a discrepancy)
as an argument against *including* the assertion.

If there is no assertion in #removeAll:, then unfolding a call to it
would indeed produce b do: [:each | a remove: each].  But then there
would be no discrepancy between the original call and the unfolded version.

If there WERE an assertion in #removeAll:, then unfolding a call to it
would ALSO copy the assertion, and there would again be no discrepancy.

	This is actually the point of view I'm coming from.  If you follow this
	style guideline fervently, then you never have to worry about "a
	removeAll: b" with a==b.

Then you don't care what #removeAll: does in that case, and should not be
unhappy if it has an assertion to cover it.

	If you like the guideline but would are lazy
	in its implementation, then you'd like to get warnings whenever you
	violate it in an erroneous or even borderline situation.  When,
	precisely, would a programmer want to do "a removeAll: b" where a==b ? 

This was explained in some detail some time ago.

First, it actually _happened_ in someone else's code.  I don't know _why_
it happened, but it happened.

Second, in the absence of a #removeAll method (note the absence of a colon)
then if you want to make a collection empty,
    myownprivatecollection removeAll: myownprivatecollection
is an obvious thing to try.

Third, the programmer who wrote the method that does a removeAll: b
might not *KNOW* whether a is b or not; they might be passed as parameters.

	It seems like you have to completely disdain the above guideline
	if you conciously write such code.
	
The guideline (don't hand out your innards) is no protection at all
against this problem.

In the second case, you might be trying to operate on your own innards.

The third case also can arise from one method passing private unshared
objects to another method in the same class, where the author of the
second method didn't know the two objects might be the same and never
thought to document the restriction s/he didn't know about anyway.

In short, aliasing can occur _within_ an object.




More information about the Squeak-dev mailing list