Search code examples
smalltalkpharosqueak

Is it possible to assign a message to a variable?


I'm studying different kinds of programming languages to see how they differ and their advantages/disadvantages.

I'm currently particularly interested in languages that use messages for method calls; and I was wondering if it's possible to somehow assign a message to a variable in Squeak/Pharo/Smalltalk/etc.

So let's say both class A and B have the message foo:; how can I then do something like this:

|msg| 
msg := foo: 12.
a msg.
b msg.

Where a and b are instances of A and B respectively


Solution

  • Pharo has Message class. So you can create it as

    Message selector: #foo: argument: 12
    

    But currently Message is not used for execution purposes.

    What you are looking for are perform: messages.

    So you can do what you need like this:

    | selector arg | 
    selector := #foo:.
    arg := 12.
    a perform: selector with: arg.
    b perform: selector with: arg
    
    "for messages of other `shape`"
    a perform: selector.
    a perform: selector with: arg with: arg. "up to 3 args"
    a perform: selector withArguments: { arg . arg }
    

    As for fancy syntax

    msg := foo: 12.
    

    does not make any sense according to Smalltalk. But what you can do is to define a class like GenericMessage with 2 instance variables: selector and arguments. Then you redefine doesNotUnderstand: on the class side like this:

    GenericMessage class >> doesNotUnderstand: aMessage
    
        ^ self new
            selector: aMessage selector;
            arguments: aMessage arguments;
            yourself
    

    Then you also define a method for Object:

    Object>>#performMessage: aGenericMessage
    
        ^ self
            perform: aGenericMessage selector
            withArguments: aGenericMessage arguments
    

    Then your code will look like this:

    |msg| 
    msg := GenericMessage foo: 12.
    a performMessage: msg.
    b performMessage: msg.