Keyword chains

Suppose I have an object x that can accept any of the selectors s1 , s2 , ..., sn . Suppose further that the result of any of these selectors running on an object is an updated object of the same type. Then I could β€œchain” these selectors (as long as they are unary messages) as I want, for example:

 x s1 s2 ... sn 

This will produce the result x s1 and apply the selector s2 , then apply the selector s3 to this result, etc. I would like to apply one or more of these selectors in some order for different 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 the selector, s1: s2: ..., sn: then the following does not work:

 x s1: a1 s2: a2 ... sn: an 

There is an operator ; :

 x s1: a1 ; s2: a2 ; ... ; sn: an 

But using cascading: each step changes the original x on this path, and I don't want to change x in this case.

To associate keyword messages, I think I have to use 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 concrete example of this might be a multidimensional array. If foo is a 3-dimensional array, and you wanted to access the object at a location 2,3,5 in the array, I think it would look like this:

 (((foo at: 2) at: 3) at: 5) some_object_selectors 

This is a trivial example, of course, but illustrates the case. You may have other types of embedded objects or another chain of sequential operations with objects in which you are interested in the final result.

Is there a more syntactically attractive way to do this in Smalltalk? I assume that there is no other operator, possibly a cousin of the operator ; (let's say we use & , for example), which would connect them, for example:

 x s1: a1 & s2: a2 & ... & sn: an 

Since I would like to apply the selectors in any or almost any desired order (for possible different results), the shape of the s1:s2:s3:... selector is too restrictive. In addition, it provides a tool that already exists in other languages, such as Ruby, where it is equivalently expressed as:

 x.s1(a1).s2(a2)...sn(an) 

Without a special operator, an alternative would be to pass an array of selector-argument pairs or, possibly, a lookup table for pairs of selector pairs. The lookup table requires an installation for transferring literals (it needs to be created and filled), which makes me lean towards the array, as I can simply write it as:

 x { {s1. a1}. {s2. a2}. ... {sn. an} } 

This is still a bit uncomfortable, and I'm not sure if it is more elegant than just using all parentheses. I am afraid that my question may be at least partially subjective, but I am interested to know what might be the best practice, and whether there is an operator that I do not know about which can help, or if someone is entertained by the Smalltalk standard body.

+7
smalltalk
source share
2 answers

Usually we provide this object x with the subject we are working on, and then request this modified item when we are done with it. Copying is pretty inefficient.

 Object subclass: #Foo instanceVariableNames: 'subject' classVariableNames: '' poolDictionaries: '' category: 'Try' order: y self subject order: y select: z self subject select: z subject ^subject ifNil: [ subject := FooSubject new ] where: x self subject where: x 
+1
source share

There seems to be some kind of confusion here.

  • Cascading is done with ; where each message is sent for the same argument.
  • Your example x s1 s2... (which you called a cascade) is called a message thread where each message is sent to the result of the previous message (due to the beautiful and elegant nature of the Smalltalk syntax, which is simply an Object message and always returns the result). And no, you cannot 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 with 1 . Order may matter. (Note that I am very reluctant to use such terribly short names as examples - this is not very Smalltalk-like .; -)
  • If your n so big that using parentheses makes it inconvenient, then, uh ... sorry, but you are doing it wrong.
    • Consider creating a method on your object to accept a few arguments.
    • Consider creating a wrapper to transfer parameters.
    • Consider using a design pattern to separate an object from the operations you want to perform on it. (Which template you need will depend on what you want to achieve, here is a good starting point .)

Instead of looking for an operator to bend Smalltalk as you wish (as you can get used to what you do in other languages), I would recommend bending Smalltalk instead (explicit naming without fear of creating more objects and methods, etc. .). Ultimately, you get more out of it, and I dare say that you get to the point where you want the simplicity and power of Smalltalk in another language.

+8
source share

All Articles