Polymorphism without protocol dilution

Mike Klein mike at twinsun.com
Mon Aug 31 19:16:12 UTC 1998

On Mon, 31 Aug 1998, Maurice Rabb wrote:

> >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.
> Good point.  I was so focused on other aspects of protocol dilution, didn't
> consider the other form or dilution I was introducing.

First off, both the above methods are incorrect since they have no
return value. (a typo, I assume)
How about

at: key ifAbsentPut: valueProvider
	^self at: key ifAbsent: [self at: key put: valueProvider value]

Now it is clear that the second parameter is expected to provide a value.
(Not necesarily a block)

I think the problem with #value is that it *is* so diluted as to be
practically meaningless.  What posible semantics (given today's
Smalltalks) could one ascribe to the message? The best I can come up with

	"Answer some appropriate object"

I especially don't like that in VW, the ValueModel protocol intends
the #value message as being functional (as in free of side-effects)
whereas the blocks use value primarily in there imperative usage.

Yet, somehow, like static typing, it never seems to be a problem,
in practice,

As long as were suggesting alternate selector names for Smalltalk-2002
how about #invoke, #invokeWith:, #invokeWith:with:

> Though this wasn't the best example to illustrate it, sometime you still
> want an variable to hold either anObject or aBlock that it can evaluate in
> the same way.  If you want to prevent dilution, you shouldn't use #value.
> However in this case IMHO I think that the name should be #asEvaluated.
> BlockContext>>#asEvaluated
>         ^self value
> Object>>#asEvaluated
>         ^self
> (I still wish the convention for Blocks wasn't #value, and was instead
> something like #evaluate.)
> --Maurice

How about

Object >> fullyEvaluated

	| result lastResult |
	result := self.
	[(lastResult := result) respondsTo: #value] whileTrue: [
		result := lastResult value.
		result = lastResult ifTrue: [^result]].

This is sort of like Mathematica's evaluation loop (without the Hold[])
  [0->[3]] fullyEvaluated   =>   3

-- Mike Klein

More information about the Squeak-dev mailing list