提问人:Ofir 提问时间:11/10/2023 更新时间:11/14/2023 访问量:46
了解使用多个冒号的 Smalltalk 方法调用
Understanding Smalltalk Method Invocation with Multiple Colons
问:
我目前正在学习 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如何处理方法调用中的冒号的见解都会有所帮助。
感谢您的帮助!
答:
除非使用括号,否则关键字消息发送将查找具有所有关键字的方法。所以,是的,第一个示例查找名为 #'max:max:' 的单个方法,第二个示例查找名为 #'gcd:factorial:' 的单个方法。如果接收方的类中没有具有预期名称的方法,则系统将报告错误。
因此,如果第二个表达式成功,那么您的图像中有一个 #'gcd:factorial' 的方法(这似乎有点令人惊讶)。你用的是什么方言和版本的Smalltalk?
在 Smalltalk 中,有三种类型的消息选择器:一元选择器(例如,)、二进制选择器(例如,)和关键字选择器(例如,、)。没有运算符优先级,但消息从左到右进行评估,您可以使用括号来控制评估顺序。2 negated
2 + 3
2 max: 3
2 min: 20 max: 10
在示例 1 中,Smalltalk 尝试查找具有三个参数的名为“max:max:”的方法,而在示例 2 中,它正确地将冒号解释为单独的消息,从而生成“gcd: 3”和“factorial: 5”。
对于我所知道的任何 Smalltalk 方言,这都是错误的。没有“选择器的自动组合”这样的东西。如果你的实现响应消息,即,或者它的超类之一为此选择器定义了一个方法,则将执行此方法。否则,将被发送到通常引发错误的对象。类似地,会触发 DNU,因为没有这样的方法。2
max:max:
SmallInteger
doesNotUnderstand:
MessageNotUnderstood
6 gcd: 3 factorial: 5
顺便说一句,我不知道有任何采用参数的阶乘方法(数学阶乘是一个一元函数,在 Smalltalk 中实现为 ,例如,),所以为了参数,我将改用它来计算接收器对参数的幂。n!
Number>>factorial
3 factorial
raisedTo:
如果要明确要首先发送,请使用括号:gcd:
(6 gcd: 3) raisedTo: 5
要首先计算幂,请使用其他括号:
6 gcd: (3 raisedTo: 5)
HTH?
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 没有消息和参数”。当你开始以这种方式看到代码时,一盏灯亮了起来,一切都突然变得有意义了。对于某些人来说,可能需要几分钟才能发生,对于其他人来说,可能需要几天时间,但不会很长。一旦它发生,你就是一个小说话者)。
评论