Polymorphism without protocol dilution

Bob Arning arning at charm.net
Wed Sep 2 00:13:32 UTC 1998


Dave,

I'm not sure I parsed this as you intended:

On Tue, 1 Sep 1998 16:55:11 -0400 "David N. Smith" <dnsmith at watson.ibm.com> wrote: 
>I don't think of this as a type issue, but an evaluation issue. When is the
>parameter evaluated: when first passed, when about to insert it into the
>collection (lazy evaluation), or never? I claim one needs all three.
>
>
>#at:ifAbsentPut:, as implemented elsewhere, evaluates the parameter
>expression before the message is sent. If it is a block then the block is
>put into the collection.
>

Are you referring to actual implementations? I seem to recall from VSE work that if the second argument is a block, then it is #value'd if the key does not exist and the result is added. Perhaps this was a local implementation (I cannot recall at this point) - do different implementations exist?

>
>#at:ifAbsentPut:, as proposed, would allow a block and evaluate its
>contents before putting the result into the collection. However, this
>prevents actually putting a block into the collection without an ugly
>contortion:
>
>   dict at: aKey ifAbsentPut: [ [ blockCode ] ]
>

It seems to me that there is a limit to this criticism: sometimes we want to insert a simple value into the dictionary, sometimes we want to to insert a simple value resulting from evaluation of a block, or we might want to insert a block obtained from evaluating a block, such as:

d at: key ifAbsentPut: [b ifTrue: [[:x | x doSomething]] ifFalse: [[:x | x doSomethingElse]]]

or even deeper levels of nested evaluation.

>
>#at:ifAbsentPutValueOf: makes this explicit. One is not putting the block
>into the collection, but the result of evaluating the block.
>
>
>Note that, for consistancy, if the thrid example is considered wrong, one
>should then make #at:put: have the same properties as #at:ifAbsentPut:. If
>a block is passed it is evaluated before putting its value into the
>collection.

I think (for internal consistency, at least) that we need to consider other #xxx:ifXxx: protocols:

e.g.: Collection>>detect:ifNone: evaluates the second argument only if no matching element is found.

FWIW: 

Symbol allInstances select: [ :x | (x findString: ':if' startingAt: 1) > 0] 

returns 59 Symbols in my image, and a cursory check suggests that they only evaluate the ifXxx: argument only when needed.

Personally, I would like to write:

d at: k ifAbsentPut: 0	"inserting (and returning) 0 if k is not a key in d"
d at: k ifAbsentPut: aBlock		"inserting (and ^) the result of evaluating <aBlock>"
d at: k ifAbsentPut: [aBlock]		"inserting (and ^) aBlock"

but I could easily live with:

d at: k put: [0]		"to insert and return 0"

Cheers,
Bob





More information about the Squeak-dev mailing list