I find the thread a bit confused in the sense

Dictionary *new* at: x ifAbsentPut: y

does not make sense (is academic), because the new dictionary will
never have x as a key. So why profile it and use that as reasoning?...

whereas

myDict at:x ifAbsentPut: y

is more interesting.

In my experience i am biased by the use of the message in the systems
that already use it heavily...however it always feels that the use of
ifAbsentXX is intentionally deferring some code because it expresses
exceptional cases in the application logic. Especially if the block
makes an object you don't want to be doing that every time and
discarding the result irrespective of the presence of the key. It does
not have to be expensive to make, just not good style near any kind of
loop.

I know some people that actually don't like the ifAbsentPut: []
variant. and prefer to be explicit, of the form

(myDict includesKey: x) ifFalse: [
   myDict at: x put: y]

where y is either a simple value or some expression.

here the test on the key has the same effect as expecting a block in
the inline ifAbsentPut: []  . It makes both forms basically the same,
with one being more compact if you prefer that. If ifAbsentPut: did
not expect the block then i think it would be a bit odd because you
would have to unroll the code in order to achieve the deferred case
which i feel is more common.

cheers,
Mike

On Tue, Oct 4, 2011 at 2:44 PM, Henrik Sperre Johansen
<[email protected]> wrote:
> On 04.10.2011 12:52, Mariano Martinez Peck wrote:
>
> Hi guys. If I tell you the selector is Dictionary >> #at:ifAbsentPut:  what
> would you expect the second parameter to be?  the value.
> So, one would do:
> Dictionary new at: #foo ifAbsentPut: 4
>
> But if you see Dictionary >>
>
> at: key ifAbsentPut: aBlock
>     "Return the value at the given key.
>     If key is not included in the receiver store the result
>     of evaluating aBlock as new value."
>
>     ^ self at: key ifAbsent: [self at: key put: aBlock value]
>
> so it expects a Block. Ok, we are in Smalltalk, so implementing #value is
> enough.
>
> Well..the previous example works, but only because we have an ugly Object >>
> value  that returns self.
> If I put instances of subclasses from ProtoObjects (proxies), that do not
> work anymore.
>
> So...my question is we do Dictionary at: #foo put: 4, why #at:ifAbsentPut:
> expects a block and not directly the value?
>
> Sven's reasons are correct I think, it's for efficiency, and elegant lazy
> initialization of a cache.
> The same reasons will never hold true when using #at:put:.
>
> in which case I need a block instead of the value object directly ?
>
> In addition to when you want delayed computation, when you have value
> objects who redefine/do not define #value ;)
>
> Cheers,
> Henry
>

Reply via email to