为什么scala需要`unary_`前缀?

时间:2013-05-20 07:56:38

标签: scala

初学者Scala问题,但我在这里找不到答案。

与C ++中的重载类似,我希望编译器可以区分一个名为-的方法,它带有一个参数(与类相同的类型)和一元版本的-它没有参数,为什么需要unary_

2 个答案:

答案 0 :(得分:69)

一元前缀运算符unary_前缀有点误导:它比一元部分更多地关于前缀部分。你需要一些方法来区分

!foo // unary prefix !

来自

foo! // unary postfix !

请记住:Scala实际上没有运营商。调用方法有两种方法,使用.或使用空格:

foo.bar(1, "two")
foo bar(1, "two")

当你有一个参数时,你可以不用括号:

foo plus(1)
foo plus 1

最后,(几乎)任何字符在标识符中是合法的:

foo plus 1
foo + 1

现在它看起来就像Scala有一个二进制中缀+运算符,但它实际上没有。它只是用普通方法调用语法调用的普通方法。

然而,我上面所说的并不是完全。如果Scala不支持运算符,那么这只是普通的方法调用,那么

2 + 3 * 4

将评估为20(例如,在Smalltalk,Self和Newspeak中),而不是14.因此,在Scala中有一个 little 位支持运算符(实际上是两个小位,实际上) )。当使用空格(所谓的“运算符语法”)而不是.调用方法时,该方法以运算符字符开头,则Scala将尊重运算符优先级。

另外一点运算符支持是有一些你喜欢的运算符,但这不能很容易地表示为方法调用。它适用于二进制中缀运算符和一元后缀运算符:

foo op bar // same as:
foo.op(bar)

foo op     // same as:
foo.op

但不是前缀或“around-fix”运算符:

!foo
foo(bar)

因此,有一些特殊的语法糖转换规则:

!foo
foo.unary_!
// same for +, - and ~

foo(bar)
foo.apply(bar)

foo(bar) = 1
foo.update(bar, 1)

foo += 1
foo.+=(1) // but if this doesn't compile, then the compiler will also try
foo = foo.+(1)

并且在方法名称中需要在字母数字和“运算符”部分之间加下划线的原因是因为您不知道是否

foo!

表示

foo.!

this.foo!

因此,foo!作为方法名称是非法的,需要将其称为foo_!

答案 1 :(得分:9)

因为在scala中创建一个名为-的方法是完全没问题的,所以它不带参数。你如何区分普通方法和一元方法?例如,!与一元修复操作符具有完全不同的含义。