简体   繁体   中英

In Smalltalk, if x is an array, and x at: 3 put: 123 will work, then how can (x at: 3) + 1 work?

That is, if we look at it as all objects and messages, then

"Did this earlier:    x := Array new: 20"
x at: 3 put: 123      "this will put 123 into slot 3"

can work only if x at: 3 return like a "cell" object, so the cell can take in an Interger object, which is 123. (or, so that the cell object can let some myContent property point to the 123 object)

Then in this case, how can

y := (x at: 3) + 567

work? Because how does a cell deal with the + message? Is it that somehow the cell object thinks it doesn't know how to handle the + message, so it looks into its content (maybe by something like self myContent ) and then return it? How does it work? I wonder also if there is a Design Pattern name for it.

x at: 3 put: 123 sends at:put: selector to x .

There is well defined priority for selectors

  1. unary ( 1 negated )
  2. binary ( 1 + 2 )
  3. keyword ( at:put: )

The number of "arguments" for keywords selector is not relevant, it will always be interpreted as a single keyword selector, so detect:ifFound:ifNone: will be interpreted as a single selector which is sent to the object rather than three separate selectors.

Now if you want to change the priority, or put one keyword selector inside another, you have to enclose it in parens.

So your x at: 3 put: 123 contains only one message: at:put: ; if you actually want to send put: to the value present at position 3 , you need to put it in parens (x at: 3) put: 123 , which is also consistent with your observation about (x at: 3) + 567 .

Equivalent syntax from other languages would be x.atPositionInsert(3, 123) , and x.atPosition(3) + 567 .

There is no "cell" object. x at: 3 put: 123 puts the Integer 123 into the Collection x at index 3 . x (the Collection, which may be of some more concrete type such as an Array) is responsible for storing the object and retrieving it when supplied with the appropriate index, but it doesn't create and store a different object. The internal workings of the Collection x are opaque from the point of view of the user of x - you don't know how x is storing the Integer in question - you only know that when you send the message at: with argument 3 to x you're going to get back what was stored there earlier - ie you'll get back 123 . So there's no "cell" object which has to interpret + - the Integer 123 is what's handling the + message.

It is very much possible to create classes which interpret arbitrary messages sent to them. In versions of Smalltalk (eg Dolphin, Visual Smalltalk) I've worked with this is done by implementing the 'special' message doesNotUnderstand: .

Hope this helps.

I might add to Peter's answer that the parenthesis is like parens in other languages, it forces the expression in parens to be evaluated first. If there are multiple parens then evaluation goes left to right. So y := (x at: 3) + 567 For (x at: 3) is evaluated first which yields 123. 123 + 567 is evaluated second which yields 690 and y is set to 690.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM