27

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

类似于 C++ 中的重载,我希望编译器可以区分一个调用的方法之间的区别,该方法-接受一个参数(与类具有相同的类型)和-不接受参数的一元版本,那么为什么unary_需要呢?

4

2 回答 2

75

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

!foo // unary prefix !

foo! // unary postfix !

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

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 中对运算符有一点支持(实际上是两个一点)。当使用空格(所谓的“运算符语法”)而不是 调用.方法时,并且该方法以运算符字符开头,则 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_!

于 2013-05-20T08:32:21.960 回答
9

因为在 scala 中创建一个名为 的方法是完全可以的-,它不需要参数。您如何区分普通方法和一元方法?例如!,作为一元的含义与作为后修复运算符的含义完全不同。

于 2013-05-20T08:08:20.500 回答