Search code examples
syntaxsmalltalkmethod-invocation

Understanding Smalltalk Method Invocation with Multiple Colons


I'm currently learning Smalltalk, and I've encountered a behavior that I find puzzling regarding method invocation with multiple colons. I understand that colons play a crucial role in specifying method names and their arguments in Smalltalk, but I'm having difficulty grasping why the following two cases lead to different outcomes:

Example 1:

100 max: 50 max: 102

Example 2:

6 gcd: 3 factorial: 5

In Example 1, Smalltalk attempts to find a method named 'max:max:' with three arguments, while in Example 2, it correctly interprets the colons as separate messages, resulting in 'gcd: 3' and 'factorial: 5'.

I would appreciate clarification on the specific syntax and structural aspects that lead to these different interpretations by the Smalltalk interpreter. Additionally, any insights into how Smalltalk processes colons in method invocations would be helpful.

Thank you for your assistance!


Solution

  • In Smalltalk, there are three types of message selectors: unary selectors (e.g., 2 negated), binary selectors (e.g., 2 + 3), and keyword selectors (e.g., 2 max: 3, 2 min: 20 max: 10). There are no operator precedences but messages get evaluated from the left to the right and you can use brackets to control the evaluation order.

    In Example 1, Smalltalk attempts to find a method named 'max:max:' with three arguments, while in Example 2, it correctly interprets the colons as separate messages, resulting in 'gcd: 3' and 'factorial: 5'.

    For any Smalltalk dialect I am aware of, this is wrong. There is no such thing as "automatic combination of selectors". If your implementation of 2 responds to the message max:max:, i.e., SmallInteger or one of its superclasses defines a method for this selector, this method will be executed. Otherwise, doesNotUnderstand: will be sent to the object which usually raises MessageNotUnderstood error. Analogously, 6 gcd: 3 factorial: 5 will trigger a DNU because there is no such method.

    By the way, I am not aware of any factorial method that takes an argument (mathematical factorial n! is a unary function and implemented in Smalltalk as Number>>factorial, e.g., 3 factorial), so for the sake of the argument I will use raisedTo: instead, which computes the exponentiation of the receiver to the argument.

    If you want to make explicit that you want to send gcd: first, use brackets:

    (6 gcd: 3) raisedTo: 5
    

    To compute the exponentiation first, use other brackets:

    6 gcd: (3 raisedTo: 5)
    

    HTH?