I would appreciate any thought on the following:
I though I would add the common method #at:ifAbsentPut: to Dictionary.
As the convention varies between dialects, I though it would be useful for the 'ifAbsentPut: parameter' to accept either a value, or a block to be evaluated.
My first iteration was:
at: key ifAbsentPut: valueObject ^self at: keyObject ifAbsent: [self at: key put: valueObject value]
For this to work would require that I add Object>>#value which I remember is a no-no, because it dilutes the BlockContext protocol as Object>>#do: diluted the Collection protocol. We replaced Object>>#do: with #in:, so with what do we replace Object>>#value?
Two sets of solutions come immediately to mind: 1) BlockContext>>#selector1 ^self value
Object>>#selector1 ^self
at: key ifAbsentPut: valueObject ^self at: key ifAbsent: [self at: key put: valueObject selector1]
selector1 could be one of the following: a) evaluate b) evaluated c) simplify d) simplified e) asValue f) asValueObject g) asEvaluated h) asEvaluatedObject i) asImmediate j) asImmediateObject
2) BlockContext>>#selector2 ^self
Object>>#selector2 ^[self]
at: key ifAbsentPut: valueObject ^self at: key ifAbsent: [self at: key put: valueObject selector2 value]
selector2 could be one fo the following: a) asBlock b) asBlockContext c) asAction
Of my suggestions I prefer set 1 over 2 because set 2 seems more circuitous. Of set 1 I prefer option e. Unfortunately, asValue is already used in other dialects to convert an Object to a ValueHolder/ValueModel. I wish they uses asValueModel (or stuck with ValueModel on: anObject) instead.
As far as names go I often wish some of the more fundamental methods were better named so that I could use the name which they currently occupy for something more appropriate (IMHO).
Which technique and selector name is recommended?
--Maurice
--------------------------------------------------------------------------- Maurice Rabb 773.281.6003 Stono Technologies, LLC Chicago, USA
Maurice Rabb wrote:
<snip> For this to work would require that I add Object>>#value which I remember is a no-no, because it dilutes the BlockContext protocol as Object>>#do: diluted the Collection protocol. We replaced Object>>#do: with #in:, so with what do we replace Object>>#value? <snip>
Just out of curiousity and because it's late and I'm in a devil's advocate mood... What's wrong with diluting protocols? I have vaguely seen threads about this, but I've never really seen (or paid attention long enough), a good reason not to dilute protocols. It's just kind of one of those unexplained commandments (too me). I have personally thought many times that it would be cool to totally blur the lines between collections and single objects in Smalltalk for quite some time. Isn't that one of the things Lisp kind of does? Why does enumeration have to be bound to a storage strategy?
-- Travis Griggs Key Technology tgriggs@keyww.com Smalltalk - 100% Pure Objects, Always had 'em, Always will!
At 0:39 -0400 8/26/98, Maurice Rabb wrote:
I would appreciate any thought on the following:
I though I would add the common method #at:ifAbsentPut: to Dictionary.
As the convention varies between dialects, I though it would be useful for the 'ifAbsentPut: parameter' to accept either a value, or a block to be evaluated.
My first iteration was:
at: key ifAbsentPut: valueObject ^self at: keyObject ifAbsent: [self at: key put: valueObject value]
For this to work would require that I add Object>>#value which I remember is a no-no, because it dilutes the BlockContext protocol as Object>>#do: diluted the Collection protocol. We replaced Object>>#do: with #in:, so with what do we replace Object>>#value?
I'd like to make a third kind of suggestion for your list. Don't mix blocks and other values. Make the protocol different. For example:
at: key ifAbsentPut: anObject self at: key ifAbsent: [ self at: key put: anObject ]
at: key ifAbsentPutValue: aBlock self at: key ifAbsent: [ self at: key put: aBlock value ]
Another effect of this suggestion is that it still allows putting blocks into dictionaries as values, while suggestions 1 and 2 do not.
Dave _______________________________ David N. Smith IBM T J Watson Research Center Hawthorne, NY _______________________________ Any opinions or recommendations herein are those of the author and not of his employer.
David N. Smith wrote:
At 0:39 -0400 8/26/98, Maurice Rabb wrote:
I would appreciate any thought on the following:
I though I would add the common method #at:ifAbsentPut: to Dictionary.
As the convention varies between dialects, I though it would be useful for the 'ifAbsentPut: parameter' to accept either a value, or a block to be evaluated.
My first iteration was:
at: key ifAbsentPut: valueObject ^self at: keyObject ifAbsent: [self at: key put: valueObject value]
For this to work would require that I add Object>>#value which I remember is a no-no, because it dilutes the BlockContext protocol as Object>>#do: diluted the Collection protocol. We replaced Object>>#do: with #in:, so with what do we replace Object>>#value?
I'd like to make a third kind of suggestion for your list. Don't mix blocks and other values. Make the protocol different. For example:
at: key ifAbsentPut: anObject self at: key ifAbsent: [ self at: key put: anObject ]
at: key ifAbsentPutValue: aBlock self at: key ifAbsent: [ self at: key put: aBlock value ]
Another effect of this suggestion is that it still allows putting blocks into dictionaries as values, while suggestions 1 and 2 do not.
Why don't we just add types to Smalltalk! Seriously people, that's what all of these messages are starting to look like. I can just see some of my methods in the future:
at: aKey ifAbsentPutValueOfOneArgBlockThatWontReturnNil: aBlock
Not that I necessarily have a better solution :). But it worries me when I see messages whose keyword parts are basically types. A little of this is OK, but I think it should be used sparingly.
-- Travis Griggs Key Technology tgriggs@keyww.com Smalltalk - 100% Pure Objects, Always had 'em, Always will!
At 14:12 -0400 8/31/98, Travis Griggs wrote: SNIP...
I'd like to make a third kind of suggestion for your list. Don't mix blocks and other values. Make the protocol different. For example:
at: key ifAbsentPut: anObject self at: key ifAbsent: [ self at: key put: anObject ]
at: key ifAbsentPutValue: aBlock self at: key ifAbsent: [ self at: key put: aBlock value ]
Another effect of this suggestion is that it still allows putting blocks into dictionaries as values, while suggestions 1 and 2 do not.
Why don't we just add types to Smalltalk! Seriously people, that's what all of these messages are starting to look like. I can just see some of my methods in the future:
at: aKey ifAbsentPutValueOfOneArgBlockThatWontReturnNil: aBlock
Not that I necessarily have a better solution :). But it worries me when I see messages whose keyword parts are basically types. A little of this is OK, but I think it should be used sparingly.
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.
#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 ] ]
#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.
Dave _______________________________ David N. Smith IBM T J Watson Research Center Hawthorne, NY _______________________________ Any opinions or recommendations herein are those of the author and not of his employer.
Dave wrote:
#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 ] ]
Personally I find this rather natural. I guess beauty is in the eye of the beholder.
#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.
Perhaps #ifTrue:ifFalse: should be renamed to #ifTrueValueOf:ifFalseValueOf: and likewise for all of the other "control" methods. Just kidding.
I expect a niladicValuable (in X3J20-speak) when I see the fragment
ifAbsent:
so I also expect ifAbsentPut: to take one.
-- Mike Klein
squeak-dev@lists.squeakfoundation.org