Scala中对象表示法为何会消除以冒号结尾方法的右结合性?
冒号结尾方法的右结合性:中缀语法 vs 对象表示法的差异
嘿,这个问题确实戳中了Scala里一个容易混淆的语法细节,咱们把它掰扯明白:
核心规则:冒号结尾方法的右结合性
Scala里有个特殊规定:所有方法名以冒号:结尾的操作符,在使用中缀语法调用时,默认是右结合的。什么意思呢?
普通的左结合方法(比如+),a + b等价于a.+(b)——调用左边对象的方法,把右边当参数。但冒号结尾的方法反过来:a +: b等价于b.+:(a)——调用右边对象的方法,把左边当参数。
看你的例子拆解
中缀调用正确写法:
3 +: List(1,2)按照右结合规则,这行代码会被解析成
List(1,2).+:(3),而List类的+:方法正好是用来在列表头部添加元素的,所以返回List(3, 1, 2),完全符合预期。中缀调用错误写法:
List(1,2) +: 3同样按右结合规则,这行代码会被解析成
3.+:(List(1,2))——但Int类根本没有+:方法,自然编译报错。这就是右结合性带来的“反直觉”效果,因为你以为是调用列表的方法,实际却变成了调用数字的方法。对象表示法(点调用)的差异:
(List(1,2)).+:(3)当你用点
.直接调用方法时,右结合性完全不生效!因为点调用是明确指定了“调用者.方法(参数)”的关系:这里调用者是List(1,2),参数是3,完全匹配List类+:方法的定义(接收一个元素,返回新列表),所以能正常执行得到正确结果。
总结一下关键点
- 中缀语法下,冒号结尾方法是右结合:
x :op y→y.:op(x)(注意是右边对象调用方法,左边当参数) - 点语法(对象表示法)下,完全遵循“调用者在前,参数在后”的常规逻辑,右结合性规则不影响,因为你已经明确指定了调用主体。
另外补充个小细节:判断是否右结合只看方法名最后一个字符是不是冒号,比如:+(结尾是加号)就是左结合,a :+ b等价于a.:+(b),别搞混啦!
内容的提问来源于stack exchange,提问作者J.Ober
相关产品推荐
相关产品推荐

