是否可以将消息分配给变量?

Is it possible to assign a message to a variable?

我正在研究不同种类的编程语言以了解它们之间的差异和 advantages/disadvantages。

我目前对使用消息进行方法调用的语言特别感兴趣;我想知道是否有可能以某种方式将消息分配给 Squeak/Pharo/Smalltalk/etc.

中的变量

所以假设 class AB 都有消息 foo:;我怎样才能做这样的事情:

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

其中 ab 分别是 AB 的实例

Pharo 有 Message class。所以你可以将其创建为

Message selector: #foo: argument: 12

但目前 Message 未用于执行目的。

您要查找的是 perform: 条消息。

所以你可以像这样做你需要的:

| 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.

根据 Smalltalk 没有任何意义。但是你可以做的是用 2 个实例变量定义一个 class,比如 GenericMessageselectorarguments。然后像这样在 class 端重新定义 doesNotUnderstand:

GenericMessage class >> doesNotUnderstand: aMessage

    ^ self new
        selector: aMessage selector;
        arguments: aMessage arguments;
        yourself

那你也定义一个方法给Object:

Object>>#performMessage: aGenericMessage

    ^ self
        perform: aGenericMessage selector
        withArguments: aGenericMessage arguments

那么您的代码将如下所示:

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

根据您是只想按消息的名称发送消息还是存储功能供以后使用,您有不同的选择。在后一种情况下,您可以使用 blocks,这是 Smalltalk 的闭包版本。您将块定义为:

block = [ :arg | arg foo: 12 ]

这意味着无论何时使用块 foo: 12 评估 arg 都会被发送到 arg。

您的代码将如下所示:

|block| 
block := [ :arg | arg foo: 12 ].
block value: a.
block value: b

P.S。我打赌你在 Objective-C 中有同样的东西,它们也被称为块