scala 运算符 重载
上周,我开始将Scala和Kotlin与Pimp我的库模式进行比较。 在该系列的第二部分中,我想讨论运算符重载。
这是第2 次后在斯卡拉与Kotlin重点series.Other职位包括:
- 斯卡拉vsKotlin:皮条客我的图书馆
- Scala vs Kotlin:运算符重载 (本文)
- Scala vs Kotlin:内联和中缀
- 斯卡拉vsKotlin:多重继承与钻石问题
总览
在深入了解具体细节之前,让我们首先尝试说明所有内容。
在具有功能(或方法)的每种语言中,允许使用一组有限的字符来定义所述功能的名称。 某些语言对允许的字符更宽容:命名函数\O/
可能是完全有效的。
其他一些人对此更为严格。 有趣的是,Java避开了在$
之外的函数名中使用符号的功能-可能是为了应对以前使用较旧语言的滥用。 它肯定处于比较宽松的范围,并且Java编译器不会编译以前的\O/
函数。
因此,即使广泛使用,名称运算符重载也会引起误导。 恕我直言,在函数名称中谈论运算符在语义上更加正确。
斯卡拉
Scala处在宽大处理范围的另一端,允许单独使用或组合使用诸如+
和£
字符来命名函数。 请注意,我找不到有关可接受字符的任何官方文档(但是这里有一些有用的讨论)。
这使库能够提供类似于操作员的功能,使其成为其API的一部分。 一个示例是属于TraversableOnce
类型的foldLeft
函数,该函数也可以用作/:
函数。
这提供了极大的灵活性,尤其是在定义DSL时 。 例如,数学:函数可以命名为π
, ∑
或√
。 另一方面,这种灵活性可能会受到滥用,因为\O/
, _
甚至|-O
是完全有效的函数名。 有人使用基于表情的API吗?
def∑(i:Int*)=i.sum
vals=∑(1,2,3,5)// = 11
Kotlin
Kotlin处于宽大处理规模的中间,因为仅可以定义一组有限的运算符 。
每个这样的运算符都有一个相应的标准功能签名。 要在类型上定义特定的运算符,应实现关联的功能并在其前面加上operator
关键字。 例如, +
运算符与plus()
方法关联。 下面显示了如何为任意新类型定义此运算符以及如何使用它:
classComplex(vali:Int,valj:Int){
operatorfunplus(c:Complex)=Complex(this.i+c.i,this.j+c.j)
}
valc=Complex(1,0)+Complex(0,1)// = Complex(1, 1)
结论
Scala的灵活性允许几乎无限的操作员功能集。 这使得它适合设计具有域名和功能名称之间接近一对一映射的DSL。 但这也依赖于隐式性:团队的每个成员,现在和将来都必须了解每个操作员。
Kotlin采取了更为安全的方法,因为它只允许定义一组有限的运算符。 但是,这些操作员无处不在,以至于初学者都知道它们及其含义(甚至经验丰富的人)。
scala 运算符 重载