Let's suppose that I have an object, x
, which can accept any one of the selectors, s1
, s2
, ..., sn
. Let's further suppose that the result of any one of these selectors operating on the object is an updated object of the same type. I could then "chain" these selectors (as long as they are unary messages) as I wish, such as:
x s1 s2 ... sn
This will take the result of x s1
and apply selector s2
, then apply selector s3
to that result, and so on. I would want to apply one or more of these selectors in some order for various results:
x s8 s2
In Smalltalk I can do this if the selectors are unary messages. However, if my selectors are keyword messages, I can no longer do this. If x
individually accepts selectors, s1:
, s2:
, ..., sn:
, then the following doesn't work:
x s1: a1 s2: a2 ... sn: an
There is the ;
operator:
x s1: a1 ; s2: a2 ; ... ; sn: an
But using the cascading: each stage modifies the original x
along the way, and I do not wish to modify x
in this case.
To chain keyword messages, I think I'm left using the following syntax with parentheses:
(...(((x s1: a1) s2: a2) ... sn: an)
Which makes me feel like I'm programming in LISP if I have 3 or more keywrod messages. A specific example of this could be a multidimensional array. If foo
is a 3 dimensional array, and you wanted to access an object at location 2,3,5 in the array, I think it would look like:
(((foo at: 2) at: 3) at: 5) some_object_selectors
That's a trivial example, of course, but illustrates the case. One might have other kinds of embedded objects, or other chain of consecutive object operations where you are interested in the end result.
Is there a more syntactically appealing way to do this in Smalltalk? I'm supposing there isn't another operator, perhaps a cousin to the ;
operator (say we use &
for example), which would chain them, such as:
x s1: a1 & s2: a2 & ... & sn: an
Since I would like to apply the selectors in any, or nearly any, desired order (for possibly different results), the selector form, s1:s2:s3:...
is too confining. Also, this gives a facility which already exists in other languages, such as Ruby, where it would be equivalently expressed as:
x.s1(a1).s2(a2)...sn(an)
Lacking a special operator, an alternative could be to pass an array of selector-argument pairs, or perhaps a lookup table of selector-argument pairs. The lookup table requires setup for passing literals (it has to be created and populated), which makes me lean toward an array since I can simply write it as:
x { {s1. a1}. {s2. a2}. ... {sn. an} }
This is still a bit clunky, and I'm not so sure this is any more elegant than just using all the parentheses. I'm afraid my question may be at least partly subjective, but I am interested knowing what the best practice might be, and whether an operator exists that I'm not aware of which may help, or whether one is being entertained by a Smalltalk standards body.
There seems to be some confusion here.
;
, where each message is sent to the same argument.x s1 s2...
example (which you called "cascading") is called message chaining, where each message is sent to the result of the previous message (due to the beautiful and elegant nature of Smalltalk's syntax, which is simply Object message
and always returns a result). And no, you can't always put them in any order. Imagine s1
is multiplyByTwo
and s2
is addTwo
, with x
having an instance variable modified by these methods that starts as 1
. Order may matter. (Please note that I'm very reluctant to use such awfully short names as examples - it's not very Smalltalk-like. ;-)n
is so large that using parentheses makes it look awkward, then, uhm... sorry, but you're doing it wrong.
Rather than looking for an operator to bend Smalltalk to your will (of how you may be used to doing things in other languages), I'd recommend bending to Smalltalk's will instead (explicit naming, not being afraid to create more objects and methods, etc.). You'll get more out of it in the long run, and I dare say you'll get to the point where you wish other language had Smalltalk's simplicity and power.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With