[BUG]Collection>>removeAll:

Richard A. O'Keefe ok at cs.otago.ac.nz
Fri Aug 23 01:55:33 UTC 2002


Marcel Weiher <marcel at metaobject.com> wrote:
	NO NEED TO SHOUT.  ;-)
	
I had to emphasise the technical term somehow,
This terminal doesn't have an "italics" key.

	So tell me, why can a specific implementation not be a definition?  

Is this a serious question?

This is like asking "why can a house not be a plan?"

	Sorry, rhetorical question:  of course it can.
	
So you think a house _can_ be a plan?

The point of a definition is to explain to a human being what something
is supposed to mean.

The point of an implementation is to tell a computer what to do.

A piece of code in a very high level language (Z, RAISE, SETL,
in some situations even Haskell or APL) can be a definition of
the purpose of some *other* piece of code, but even then, not
of itself.

	> Not only that, it is a buggy implementation.
	
	An underdocumented one.
	
No, it is an implementation which HAS documentation (just) sufficient to
tell people what the method is for, how to use it, and so on.  It is
perfectly possible to make the method do pretty much what the comment says.

The code does not do what the comment says,
and what it _does_ do in some cases is not what anyone is likely to want.

	> On this view, it would be impossible for any bugs to exist anywhere,
	> because "the definition of" anything would not be "an English 
	> description
	> of what it does" but the code itself.
	
	When in doubt, that is quite often the "more correct" of the two.
	
This thread is not about code and comments in general, but about very
specific methods.  In this case, the comments describe something useful
which obviously makes sense in many different cases, and COULD be
implemented to work in all those cases.

Code that demonstrably gives crazy answers, when sensible answers are
possible and would suit (a reading of) the comment quite well, is not
code that can be regarded as 'the "more correct" of the two' by any
stretch of the imagination.

	> 1. Designers accepting "done change a collection you are iterating 
	> over"
	>    as a reasonable constraint on use.
	>
	>    I've cited Java above partly in order to defend this decision.  
	> Making
	>    copies to make #do: safe may seem reasonable on a 250MHz 64MB 
	> machine;
	
	Actually, I'd contend that it still isn't reasonable, because making a 
	copy of something just to iterate over it is just as unexpected as not 
	being able to removeAll:self.  What if the collection doesn't like 
	being copied, or require a deep-copy?  What if it is huge and copying 
	makes us run out of memory?  What if the collection is a multi-gigabyte 
	disk-database?
	
Well, it's something I'm not recommending, anyway.
That was a concession to the person I was replying to.
"may seem" ~= "is"

As a matter of fact, multi-gigabyte databases *do* have virtual-copy
semantics.  If I ask

    DELETE FROM transfers
      WHERE source NOT IN (SELECT destination FROM transfers);

in SQL, there are at least two ways to do it:

    dd := transfers collectAsSet: [:each | each destination].
    transfers removeAllSuchThat: [:each | dd includes: each source].

and

    transfers := transfers reject: [:each |
	transfers anySatisfy: [:xfer | each source = xfer destination]].

Whatever actually goes on, I should get the same result.
Chances are, it _will_ involve some copying, but that's the implementor's
problem, not mine.

(Think about mapping database queries onto Smalltalk, and then think
about Collection methods with strange cases that don't quite work.)

By the way, I love Smalltalk, and I love Squeak,
I just wish I was a billionaire so that I could donate a lot of
money to Squeak support.

<CSOTD>
    Collection>>
    collectAsSet: aBlock
	"Evaluate aBlock with each of the reciever's elements as argument.
	 Collect the results into a Set, and answer the new Set.
	 This is like (self collect: aBlock) asSet, but it doesn't
	 waste time building some other data structure and converting it."

	|newSet|
	newSet := Set new.
	self do: [:each | newSet add: (aBlock value: each)].
	^newSet
</CSOTD>

I like it.  I think I'll keep it.




More information about the Squeak-dev mailing list