Reputation: 12144
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
Upvotes: 3
Views: 542
Reputation: 13396
Depending whether you want just to send a message by it's name or store functionality for later use, you have different options. In the latter case you can use blocks which are Smalltalk's version of closures. You define a block as:
block = [ :arg | arg foo: 12 ]
this means that whenever you evaluate an arg with the block foo: 12
will be sent to the arg.
Your code will look like this then:
|block|
block := [ :arg | arg foo: 12 ].
block value: a.
block value: b
P.S. I bet you have the same thing in Objective-C and they are also called blocks
Upvotes: 1
Reputation: 13396
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 }
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.
Upvotes: 3