Protocol dilution?

Doug Way dway at mat.net
Tue Dec 22 19:29:33 UTC 1998


Sorry for a belated response, but this composite wrapper scheme seems
cooler each time I look at it. 
 
(By the way, I'm not really that familiar with what the term "composite" 
means in a computer science/math sense... is it fair to say that a
"composite" is something that represents either one object or a collection
of objects?) 
 
Anyway, a few questions follow... 
 
On Wed, 16 Dec 1998, Marcel Weiher wrote: 

> > I was thinking more of passing an argument to a method. If the
> > argument is a single object, you would simply send it arg1 #fire,
> > on the other hand, if the argument is a collection arg1 #fire will
> > fail. On the other hand, if single objects understand do: then
> > arg1 do: [each: each #fire] will work.  I dont see how collect
> > solves this problem?
>
> Yes, single arguments/receivers are wrapped so that they repeat in
> the presence of collection arguments/receivers.  So:
>
>       2 collect raisedTo: (1 to: 20)
>
> repeats the receiver '2' while stepping through the argument
> collection, sending the messages 2 raisedTo: 1,  2 raisedTo: 2, 2
> raisedTo: 3 etc.

I was wondering exactly how this would be implemented... I guess "2
collect" would return a special Composite object?  This Composite object
would then automatically forward any methods sent to it (e.g. raisedTo: ) 
to its component object or collection, iterating if it's a collection.  No
problem, I think. 
 
But it sounds like it would take a look at the arguments passed along with
the methods (e.g. (1 to: 20)) and determine if any of those are
collections, and then iterate appropriately.  This part is trickier now... 
what if a method normally has a collection as one of its arguments?  How
would it know when to iterate, and when to simply pass the collection
along as a single argument?  For example: 
 
2 collect addAll: (3 to: 10). 
 
I suppose you could just lay down the rule that all messages sent to
composites will have their collection arguments iterated through, so you'd
never want to send something like addAll: to a composite.  (Or, it might
be safer to get rid of the collection-argument iterating altogether.) 
 
> In your case, you one would probably use #do instead of #collect, making
> the example read
> 
>       arg1 do fire

So it sounds like "arg1 do" would also return a Composite object, but it
would need to keep track of the fact that it is about to "do" any messages
sent to it, rather than "collect".  Maybe there should be different
subclasses for each major type of iteration, such as a DoComposite, a
CollectComposite, SelectComposite, etc.  Or, just have the one Composite
class internally keep track of whether it's about to do a "do", "collect",
etc... this is probably simpler. 
 
Anyway, what I like about this scheme is that (in addition to handling
messages to single objects and collections) it can get rid of the need to
always use blocks for simple iterations, simplifying a lot of code.  As
your example shows: 
 
arg1 do fire
 
is a lot more concise (and probably more readable to a novice) than
 
arg1 do: [:each | each fire]
 
I guess this only works where "each" is the first item after the vertical
bar, but that's often the case for most iterations. 
 
I wonder what the performace implications of this scheme would be... I
suppose creating a Composite object for every iteration might be a bad
thing, but maybe optimizable... 

> Btw, don't nail me down on specifics of the syntax, I am just
> experimenting in this direction and especially the syntactic aspects
> seem to have bewildering trade-offs. 
 
True enough. :) 

- Doug Way
  dway at mat.net
  dway at transom.com
  http://www.transom.com





More information about the Squeak-dev mailing list