[BUG]Collection>>removeAll:

Richard A. O'Keefe ok at cs.otago.ac.nz
Mon Aug 26 00:25:31 UTC 2002


I wrote:
    > Procedures, functions, methods or whatever should be so designed that 
    > they do not return garbage silently.

"Andrew C. Greenberg" <werdna at mucow.com> wrote:
	
    It seems to me that a correct diagnosis as to whether all
    parameters of all functions fall within the computable range of every
    function may be a something of a breakthrough in recursive function
    theory.  We might use such a process to help solve the halting problem.

Once again, we're in the land of Red Herrings and Straw Men.

It is indeed impossible to solve the halting problem,
which is "given an ENTIRELY ARBITRARY recursive function, determine whether
or not it halts.

That does NOT mean that it is impossble for human beings to DESIGN
functions that halt.

In the same way, whether or not it is possible to determine whether
"all parameters of ***ALL*** functions fall within the computable range
of ***EVERY*** function" is not the point at issue; whether it's possible
or not, it need not stop us ***DESIGNING*** functions so that they
don't return garbage silently.

I am not arguing, and never have argued, that some kind of magical
instrumentation should be added to Squeak to detect every possible
problem in existing code, no matter how badly written, no matter whether
designed or not.

What I wrote was that "... methods SHOULD BE SO ***DESIGNED*** that they
do not return garbage silently."

No magic, no theoretical impossibilities, just a request that from time
to time people would _think_ about what they write.

	As a practical matter, I would always prefer that erroneous
	inputs be identified and flagged.

Or alternatively, that the method BE SO DESIGNED THAT inputs only count
as "erroneous" when there is no sensible beahviour that could feasibly
ensue.

	However, I'm not sure Richard is proposing a 
	solution that satisfies his own requirements.

	By using an ad hoc solution for a parameter not in the range of
	a coherent definition of the function, all he has done is to widen
	(silently) the definition from a general recursive function to another
	general recursive function of the form:  do this, except in this special
	case, in which case do that.

This is a radically unfair characterisation of what I've done.

1.  I have *NOT* in any way widened the definition.

    I have merely implemented the definition that I found already existing
    in the ANSI 1.9 draft and in the Squeak comments.

2.  The solution is not ad hoc.  The bug exists because the code is
    vulnerable to aliasing.  Removing the aliasing and the bug goes away.        
    Making a copy is a general way to remove aliasing.  When I made the
    correction, I felt that I did not have any choice; short of rewriting
    #removeAll: completely in the classes where it really belonged, this
    was the _only_ plausible change.

An important thing to remember is that #removeAll: isn't a function.
It's a 'procedure' whose purpose is to modify an object.  The result is
not well defined and I have been unable to find any code that actually
uses it.

	I think Richard argued passionately and credibly, but I'm with
	Ralph and David on this one.
	
Then you still haven't understood me.
Let's repeat the point one more time in the hope that this time it
might get through.

    > Procedures, functions, methods or whatever should be so designed that 
    > they do not return garbage silently.

What does this tells us about #removeAll:?
	
It should be DESIGNED so that it doesn't return garbage silently.

What's wrong with the existing code?

It has an aliasing bug.

What should be done about that?

- Either fix the implementation so that garbage is not returned at all
  (my preferred choice)

- Or fix the implementation so that garbage is not returned SILENTLY
  (my second preference)

Why doesn't this take us into Halting Problem terrority?

Because we simply are not talking about ALL functions, we are talking
about ONE method, for which detecting the aliasing that is likely in
practice is dead simple.

As I have said before in other words, something like

    removeAll: aCollection
        self == aCollection ifTrue: [
	    self error: 'parameter aliased with receiver; stupid code'].
	^aCollection do: [:each | self remove: each]

would not be as useful as a method that worked in all cases,
but it _would_ be code that you could recommend with a straight face
and a clear conscience.

Whether it would be this easy in other cases is so far beyond the point
that you couldn't see it with the Hubble telescope; it's this easy in
THIS case.




More information about the Squeak-dev mailing list