#at:ifAbsent... (was: Polymorphism without protocol dilution)

Mike Klein mike at twinsun.com
Wed Sep 2 04:06:30 UTC 1998



On Tue, 1 Sep 1998, Maurice Rabb wrote:

> find the key.  He is _not_ suggesting that we break from the consistent
> behavior of all the other ifXxxx: protocols.

In some sense, he is, since the ifXxxx: protocols often take a block of
defered code, e.g. ifTrue: []

> >>#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.
> >>
> 
> Again this is what he means:
> 
>                   anInteger _ dict at: '22!' ifAbsentPut: (22 factorial)
>                                                                    ^
> "evaluates the parameter expression before the message is sent" ---|
> 
>    aBlock _ dict at: 'bobs example'
>                  ifAbsent: (aBoolean ifTrue: [ [:x | x doSomething] ]
>                                      ifFalse: [ [:x | x doSomethingElse] ])
>                                                                    ^
> "evaluates the parameter expression before the message is sent" ---|

Parameter expressions are *always* evaluated before messages are sent.
In my mind, this is one of the niceties of Smalltalk over Scheme...
there are no special forms.  If the parameter is a block, it evaluates
to a BlockContext (or closure... hopefully, someday)

> Yes, unfortunately different dialects of Smalltalk implement
> #at:ifAbsentPut: with different semantics.  

Bummer.

> >>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.
> 
> To restate the above: If #at:ifAbsentPut: behaves such that it accepts
> either a simple value or a block, using the value of the block if it is a
> block, then #at:put: should behave the same. Thus:
> 
> dict at: 1 put: 10 factorial            "puts a 3628800"
> dict at: 2 put: [10 factorial]          "puts a 3628800"
> dict at: 3 put: [ [10 factorial] ]      "puts a block"
> 
> IMHO, these semantics are not just ugly, but "astonishing"! 
> I vote for Dave's.

And in my opinion, it is the 'ifAbsent' fragment that is the indicator
that the method expects a valuable (valueProvider), not the put.  This
is fairly consistent.

There is, however, the issue of which objects should be self-evaluating,
i.e.  (x value = x), so, if, using my prefered semantics of at:ifAbsent: ,
one may write 
	dict at: key put: 3   "presuming that (3 value = 3), not DNU"

-- Mike Klein





More information about the Squeak-dev mailing list