marcel at system.de
Tue Dec 22 21:57:23 UTC 1998
> Sorry for a belated response, but this composite wrapper scheme seems
> cooler each time I look at it.
Thank you! I am glad somebody out there likes it!
> (By the way, I'm not really that familiar with what the term
> means in a computer science/math sense... is it fair to say that a
> "composite" is something that represents either one object or a
> of objects?)
The 'composite' part actually refers to the composite pattern that
Peter Smet was working on and has nothing to do with my scheme, which
doesn't really have a name yet.
[ Example: 2 collect raisedTo:#(1 to: 10) ]
> I was wondering exactly how this would be implemented... I guess "2
> collect" would return a special Composite object? This Composite
> would then automatically forward any methods sent to it (e.g.
> to its component object or collection, iterating if it's a
> problem, I think.
That's pretty much it. The implementation actually uses various
types of streams in order to have a scheme that is very
compositional. These 'filter'-streams, modelled after UNIX filters,
take another stream as input. The ultimate source can be a stream
over a collection, a single object (sometimes turned into an infinite
repeater), or some sort of generator. Maybe an object returning
lines from a text file?
> But it sounds like it would take a look at the arguments passed
> the methods (e.g. (1 to: 20)) and determine if any of those are
> collections, and then iterate appropriately. This part is trickier
> what if a method normally has a collection as one of its
> 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
> never want to send something like addAll: to a composite. (Or, it
> be safer to get rid of the collection-argument iterating altogether.)
Yes, it probably is safer to do just that, and that's one of the
variants I have examined. This requires 'streaming' arguments to be
2 collect raisedTo:(2 to: 10) collect
2 collect raisedTo:(2 to: 10) each
Which variant is better is one of the questions that should be
resolved, though I somewhat favor the explicit approach, even if it
is a little more typing, because it is much more orthogonal and
probably adheres better to the principle of least astonishment.
> 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
> 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
> bar, but that's often the case for most iterations.
arg1 do: [ :each | someOtherObject fire:each ]
someOtherObject do fire: arg1 each
As you noted for the other examples, I think this is also somewhat
more natural, because it preserves the original message:
someOtherObject fire: arg1
and just adds a little embellishment that says 'send this message
not just to a single object but to several'. It's really a sort of
multicast for Smalltalk messages, and it gets you thinking what other
funky things could be done with messages/operations ...
> 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...
Currently, it is significantly slower than block-style iteration. I
haven't narrowed it down yet, but I think the major overhead is
probably sending Message objects via 'sentTo:' instead of direct
byte-coded messages. There are several ways of making it fast again,
the coolest probably using some sort of meta-level constructs.
Again, thanks for the feedback. I am off on vacation now, so a
happy holiday season to everyone and let's talk more in January.
More information about the Squeak-dev