As shown in the previous section, there are many cases in which the purpose of a message is to cause some change inside the receiver, rather than to obtain some new object to work with. In these cases, the method corresponding to the message will return the receiver, so that new messages may be "appended" after the first message to the same object.
receiver
Method 1
receiver message 1
message 2
Method 2
Since every message has as a result an object returned by the receiver, one can send to the result of one message another message, by appending one more dot-message after the first message. One can thus create chains of messages of any length.
SCWindow.new; // Create a window.
// The window will be invisible until brought to the front SCWindow.new.front // Create a window and make it visible
(Use the mouse to close the window just created before continuing)
SCWindow.new.front.view // get the main view of the window just created
(Use the mouse to close the window just created before continuing)
// get the main view of the window and set its background color to red: SCWindow.new.front.view.background_(Color.red)
(Use the mouse to close the window just created before continuing)
When chaining messages, it is essential to know which object is returned by each message in turn. If for example one wants to set the name of the window by chaining a new message to the above statement, the new message must be addressed to the window, not to the view. Since the
view message returns the main view of the window, one must place the message that sets the name
before getting the view, not after it.
// wrong: name_ message sent to the view is not understood and results in error
SCWindow.new.front.view.background_(Color.red).name_("a new window") // correct
A Very Step-by-Step Guide to SuperCollider
84/...124
The language
Communication between Objects: Messages
Chaining several messages in one statement
As shown in the previous section, there are many cases in which the purpose of a message is to cause some change inside the receiver, rather than to obtain some new object to work with. In these cases, the method corresponding to the message will return the receiver, so that new messages may be "appended" after the first message to the same object.
receiver
Method 1
receiver message 1
message 2
Method 2
Since every message has as a result an object returned by the receiver, one can send to the result of one message another message, by appending one more dot-message after the first message. One can thus create chains of messages of any length.
SCWindow.new; // Create a window.
// The window will be invisible until brought to the front SCWindow.new.front // Create a window and make it visible
(Use the mouse to close the window just created before continuing)
SCWindow.new.front.view // get the main view of the window just created
(Use the mouse to close the window just created before continuing)
// get the main view of the window and set its background color to red: SCWindow.new.front.view.background_(Color.red)
(Use the mouse to close the window just created before continuing)
When chaining messages, it is essential to know which object is returned by each message in turn. If for example one wants to set the name of the window by chaining a new message to the above statement, the new message must be addressed to the window, not to the view. Since the
view message returns the main view of the window, one must place the message that sets the name
before getting the view, not after it.
// wrong: name_ message sent to the view is not understood and results in error
SCWindow.new.front.view.background_(Color.red).name_("a new window") // correct
SCWindow.new.front.name_("a new window").view.background_(Color.red)
Error: "Message not understood"
The example of wrong order in the chaining of messages above causes an error message
"Message 'name_' not understood. Such a message will occur every time that an object does not understand a message. Let's try this again:
SCWindow.new.front.view.background_(Color.red).name_("a new window")
Here is the entire error message posted by the system:
ERROR: Message 'name_' not understood. RECEIVER:
Instance of SCTopView { (06AD45D0, gc=98, fmt=00, flg=00, set=04) instance variables [11]
dataptr : RawPointer 657B420 parent : nil
action : nil
background : instance of Color (06A98B10, size=4, set=2) keyDownAction : nil keyUpAction : nil keyTyped : nil beginDragAction : nil onClose : nil children : nil decorator : nil } ARGS:
Instance of Array { (069C8660, gc=98, fmt=01, flg=00, set=01) indexed slots [1]
0 : "a new window" }
CALL STACK:
DoesNotUnderstandError-reportError 074D6430
arg this = <instance of DoesNotUnderstandError> Nil-handleError 07CB9A90
arg this = nil
arg error = <instance of DoesNotUnderstandError> Object-throw 06B16650
arg this = <instance of DoesNotUnderstandError> Object-doesNotUnderstand 06A19B00
arg this = <instance of SCTopView> arg selector = 'name_'
arg args = [*1]
Interpreter-interpretPrintCmdLine 06CA2EA0 arg this = <instance of Interpreter> var res = nil
var func = <instance of Function> Process-interpretPrintCmdLine 07D11A10
arg this = <instance of Main>
Immediately below the first line of the error message (ERROR: ...) follows a printout of the receiver of the message that caused the error and of the contents of that receiver. Here, the receiver is "An instance of SCTopView". ...
A Very Step-by-Step Guide to SuperCollider
85/...124
The language
Communication between Objects: Messages
Error: "Message not understood"
The example of wrong order in the chaining of messages above causes an error message
"Message 'name_' not understood. Such a message will occur every time that an object does not understand a message. Let's try this again:
SCWindow.new.front.view.background_(Color.red).name_("a new window")
Here is the entire error message posted by the system:
ERROR: Message 'name_' not understood. RECEIVER:
Instance of SCTopView { (06AD45D0, gc=98, fmt=00, flg=00, set=04) instance variables [11]
dataptr : RawPointer 657B420 parent : nil
action : nil
background : instance of Color (06A98B10, size=4, set=2) keyDownAction : nil keyUpAction : nil keyTyped : nil beginDragAction : nil onClose : nil children : nil decorator : nil } ARGS:
Instance of Array { (069C8660, gc=98, fmt=01, flg=00, set=01) indexed slots [1]
0 : "a new window" }
CALL STACK:
DoesNotUnderstandError-reportError 074D6430
arg this = <instance of DoesNotUnderstandError> Nil-handleError 07CB9A90
arg this = nil
arg error = <instance of DoesNotUnderstandError> Object-throw 06B16650
arg this = <instance of DoesNotUnderstandError> Object-doesNotUnderstand 06A19B00
arg this = <instance of SCTopView> arg selector = 'name_'
arg args = [*1]
Interpreter-interpretPrintCmdLine 06CA2EA0 arg this = <instance of Interpreter> var res = nil
var func = <instance of Function> Process-interpretPrintCmdLine 07D11A10
arg this = <instance of Main>
Immediately below the first line of the error message (ERROR: ...) follows a printout of the receiver of the message that caused the error and of the contents of that receiver. Here, the receiver is "An instance of SCTopView". ...