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
|