[GOODIE] invarAssn-raok

Richard A. O'Keefe ok at cs.otago.ac.nz
Thu Aug 29 05:20:02 UTC 2002


I posted InvariantKeyAssocation,
    "a subclass of Association which can be safely used when the key
     must not be replaced."

Tommy Thorn <thorn at meko.dk> wrote:
	1) What exactly does it mean to replace the key?

Suppose you do
    x := Association key: #foo value: 27.
The basic operations now available are
    x value		=> 27
    x value: 99		changes x, returns x.  x value will now be 27
    x key		=> #foo
    x key: #bar		changes x, returns x.  x key will now by bar.

Basically all that InvariantKeyAssocation does is block this last message.

	I assume that it assumes the association itself as a mutable object

Yes, they are.  Always have been.

	where the key can be updated (which is not ok), whereas deleting
	a pair (k,v) and inserting a new (k',v) is ok?
	
Right.  This is a building block for a new version of Dictionary (NOT
a change to Dictionary, a whole new class).  However, I'm _really_ supposed
to be writing exam questions, so it may be some time before I get to finish
the rest of it, and I thought this chunk might be useful as it stands.

	2) What is the advantage of InvariantKeyAssociation / when
	should it be preferred?
	
Consider

    aDictionary associationsDo:
	[:eachAssociation | eachAssociation key: nil].

This doesn't actually make sense, but Squeak won't stop you doing it.
InvariantKeyAssociations are associations with a key you can't change,
so my new Dictionary-like class will be able to hand its associations
out safe in the knowledge that which object the key _is_ can't be changed.
The values can be changed, indeed that's one reason why #assocationsDo:
is useful.  But the values aren't used to structure the dictionary.
The key objects may be mutated, but the ANSI Smalltalk standard says
over and over again "don't do that", so I think we can expect people to
know not to change the keys themselves.

Note that it is possible to imagine an implementation of
#associationsDo: in which changes to the keys were allowed and worked.
Here's one:

    associationsDo: aBlock
	|deltas old|
	
	deltas := OrderedCollection new.
	super do: [:eachAssociation |
	    old := eachAssociation key.
	    aBlock value: eachAssocation.
	    eachAssociation key ~= old
		ifTrue: [deltas addLast:
			    {old. eachAssocation key. eachAssociation value}.
			 eachAssociation key: old]].
	deltas do: [:eachTriple |
	    self remove: (eachTriple at: 1).
	    (eachTriple at: 2) ifNotNil: [
	        self at: (eachTriple at: 2)
	             put: (eachTriple at: 3)].

This lets aBlock change a key; it notes the change and puts the old key
back so that the structural properties of the Dictionary are preserved
while the #do: is happening.  (No, I am NOT proposing that #associationsDo:
be changed.  Nor am I suggesting that it _should_ have been like this.
I'm only trying to stave off the inevitable comments that any Smalltalk
programmer should just _know_ as a universal constraint across all
programming languages that it isn't going to work.  Well, it could have.)

We REALLY need better comments in Squeak.
Dictionary>>associationsDo: just says
    "Evaluate aBlock for each of the receiver's elements
     (key/value associations)."

It should say something like
    "Pass each of the receivers (key->value) Associations to
     aBlock in an unspecified order.  aBlock may change the
     value of an Association, but should not change any key."




More information about the Squeak-dev mailing list