了解使用多个冒号的 Smalltalk 方法调用

Understanding Smalltalk Method Invocation with Multiple Colons

提问人:Ofir 提问时间:11/10/2023 更新时间:11/14/2023 访问量:46

问:

我目前正在学习 Smalltalk,我遇到了一种行为,我发现使用多个冒号的方法调用令人费解。我知道冒号在 Smalltalk 中指定方法名称及其参数方面起着至关重要的作用,但我很难理解为什么以下两种情况会导致不同的结果:

示例 1:

100 max: 50 max: 102

示例 2:

6 gcd: 3 factorial: 5

在示例 1 中,Smalltalk 尝试查找具有三个参数的名为“max:max:”的方法,而在示例 2 中,它正确地将冒号解释为单独的消息,从而生成“gcd: 3”“factorial: 5”。

我希望能澄清导致 Smalltalk 解释器做出这些不同解释的具体语法和结构方面。此外,任何关于Smalltalk如何处理方法调用中的冒号的见解都会有所帮助。

感谢您的帮助!

语法 smalltalk 方法-调用

评论


答:

2赞 James Foster 11/10/2023 #1

除非使用括号,否则关键字消息发送将查找具有所有关键字的方法。所以,是的,第一个示例查找名为 #'max:max:' 的单个方法,第二个示例查找名为 #'gcd:factorial:' 的单个方法。如果接收方的类中没有具有预期名称的方法,则系统将报告错误。

因此,如果第二个表达式成功,那么您的图像中有一个 #'gcd:factorial' 的方法(这似乎有点令人惊讶)。你用的是什么方言和版本的Smalltalk?

3赞 Christoph Thiede 11/10/2023 #2

在 Smalltalk 中,有三种类型的消息选择器:一元选择器(例如,)、二进制选择器(例如,)和关键字选择器(例如,、)。没有运算符优先级,但消息从左到右进行评估,您可以使用括号来控制评估顺序。2 negated2 + 32 max: 32 min: 20 max: 10

在示例 1 中,Smalltalk 尝试查找具有三个参数的名为“max:max:”的方法,而在示例 2 中,它正确地将冒号解释为单独的消息,从而生成“gcd: 3”和“factorial: 5”。

对于我所知道的任何 Smalltalk 方言,这都是错误的。没有“选择器的自动组合”这样的东西。如果你的实现响应消息,即,或者它的超类之一为此选择器定义了一个方法,则将执行此方法。否则,将被发送到通常引发错误的对象。类似地,会触发 DNU,因为没有这样的方法。2max:max:SmallIntegerdoesNotUnderstand:MessageNotUnderstood6 gcd: 3 factorial: 5

顺便说一句,我不知道有任何采用参数的阶乘方法(数学阶乘是一个一元函数,在 Smalltalk 中实现为 ,例如,),所以为了参数,我将改用它来计算接收器对参数的幂。n!Number>>factorial3 factorialraisedTo:

如果要明确要首先发送,请使用括号:gcd:

(6 gcd: 3) raisedTo: 5

要首先计算幂,请使用其他括号:

6 gcd: (3 raisedTo: 5)

HTH?

0赞 Jim Sawyer 11/14/2023 #3

Smalltalk代码是这样写的

100 max: 50 max: 102.

is sending a #max:max: message  (which is one keyword message,
                                 composed of two 'keyword' parts
                                 'max:' and 'max:', and so expects
                                 two arguments)
to the receiver, which in this case is the integer 100.

本质上等同于调用一个类似 C 的函数,写成

answer = selfMaxMax(100, 50, 102);

可以将其描述为具有三个参数的函数。 我说“本质上是等价的”,因为人们可以这样看待事物, 在学习的同时来回翻译。但实际上不要这样做。

你要学会把代码看作是“一个接收器、一条消息和一些参数”。
因为你可以递归地组合这些东西。因为每个参数只是一些额外的代码,带有“接收器、消息和一些参数”。例如,上面的 #max:max: 消息有两个参数,其中一个参数是“接收器 50 没有消息且没有参数”,另一个参数是“接收器 102 没有消息和参数”。当你开始以这种方式看到代码时,一盏灯亮了起来,一切都突然变得有意义了。对于某些人来说,可能需要几分钟才能发生,对于其他人来说,可能需要几天时间,但不会很长。一旦它发生,你就是一个小说话者)。