Search code examples
methodsmessagesmalltalk

Can you store functions in variables?


I am currently studying a bit of Smalltalk.

Is there a way you can store a function or method inside a variable?

For example, in Python one could say:

x = someobject.method
x() # calling it

Is this possible in Smalltalk? What about passing something.method itself as an argument to another method?


Solution

  • You can get a method object, by asking the class object for a method with a given name. Below >> is a message send to the class Object with the method name as a parameter.

    Object >> #asString

    This returns an instance of type CompiledMethod. This is an object representing a method. Like any object you can store it inside a variable.

    copyMethod := Object>>#asString.

    For example, if you open in Pharo a Playground and inspect the code above you get:

    executing code in playground

    You can then execute the method using the message #valueWithReceiver:arguments:. This needs as a parameter the receiver (self/this) and possible arguments.

    result := copyMethod 
        valueWithReceiver: Object new arguments: #().
    

    executing the method

    However, this is a low level way to execute a method.

    I'd say more common is to the directly execute a method with a given name on an object. That can be done using perform: or perform:withArguments:. You can send this to the object with the method name as argument

    receiver := Object new.
    receiver perform: #asString.
    

    The code above executes the method named asString on the receiver object. This is often used to pass the names of methods that we need to execute. The difference is that instances of CompiledMethod are immutable. If you change the code of that method a new instance is created and you can end up executing an older version of the method.