Scala操作符的優(yōu)先級和關(guān)聯(lián)性
操作符的優(yōu)先級決定了表達(dá)式的哪個部分先于其他部分被評估。舉例來說,表達(dá)式2 + 2 * 7計算得16,而不是28,因為*操作符比+操作符有更高的優(yōu)先級。因此表達(dá)式的乘法部分先于加法部分被評估。當(dāng)然你還可以在表達(dá)式里使用括號來厘清評估次序或覆蓋優(yōu)先級。例如,如果你實際上希望上面表達(dá)式的值是28,你可以這么寫表達(dá)式:
51CTO編輯推薦:Scala編程語言專題
- (2 + 2) * 7
由于Scala沒有操作符,實際上,是以操作符的格式使用方法的一個途徑,你或許想知道操作符優(yōu)先級是怎么做到的。Scala基于操作符格式里方法的第一個字符決定優(yōu)先級(這個規(guī)則有一個例外,稍后再說)。比方說,如果方法名開始于*,那么就比開始于+的方法有更高的優(yōu)先級。因此2 + 2 * 7將被評估為2 + (2 * 7),而a +++ b *** c(這里a,b和c是值或變量,而+++和***是方法)將被看作是a +++ (b *** c),因為***方法比+++方法有更高的優(yōu)先級。
表格 5.3 操作符優(yōu)先級
表格5.3以降序方式展示了根據(jù)方法第一個字符指定的優(yōu)先級,同一行的字符具有同樣的優(yōu)先級。表格中字符的位置越高,以這個字符開始的方法具有的優(yōu)先級就越高。舉例如下:
<<方法開始于字符<,在表格5.3里的位置比+(+方法的第一個也是唯一的一個字符)要低。因此<<比+的優(yōu)先級低,表達(dá)式也要在先調(diào)用了+方法之后再調(diào)用<<方法,如2 << (2 + 2)。我們可以算一下,2 + 2得4,2 << 4得32。下面給出另一個例子:
- scala> 2 << 2 + 2
- res41: Int = 32
由于第一個字符與前面的例子里一樣,因此調(diào)用的方法順序也沒有不同。首先+方法被調(diào)用,然后是<<方法。因此2 + 2得4,4 << 2得16。
- scala> 2 + 2 << 2
- res42: Int = 16
上面提到的優(yōu)先級規(guī)則的一個例外,有關(guān)于以等號結(jié)束的賦值操作符:assignment operator。如果操作符以等號字符(=)結(jié)束,且操作符并非比較操作符<=,>=,==,或=,那么這個操作符的優(yōu)先級與賦值符(=)相同。也就是說,它比任何其他操作符的優(yōu)先級都低。例如:
與下面的相同:
- x *= y + 1
因為*=被當(dāng)作賦值操作符,它的優(yōu)先級低于+,盡管操作符的第一個字符是*,似乎其優(yōu)先級高于+。
- x *= (y + 1)
當(dāng)同樣優(yōu)先級的多個操作符肩并肩地出現(xiàn)在表達(dá)式里,操作符的關(guān)聯(lián)性:associativity決定了操作符分組的方式。Scala里操作符的關(guān)聯(lián)性取決于它的最后一個字符。正如第3章里47頁提到的,任何以‘:’字符結(jié)尾的方法由它的右手側(cè)操作數(shù)調(diào)用,并傳入左操作數(shù)。以其他字符結(jié)尾的方法有其他的說法。它們都是被左操作數(shù)調(diào)用,并傳入右操作數(shù)。因此a * b變成a.*(b),但是a:::b變成b.:::(a)。然而,不論操作符具有什么樣的關(guān)聯(lián)性,它的操作數(shù)總是從左到右評估的。因此如果b是一個表達(dá)式而不僅僅是一個不可變值的指針的話,那么更精確的意義上說,a:::b將會當(dāng)作是:
- { val x = a; b.:::(x) }
這個代碼塊中,a仍然在b之前被評估,然后評估結(jié)果被當(dāng)作操作數(shù)傳給b的:::方法。
這種關(guān)聯(lián)性規(guī)則在同時使用多個具有同優(yōu)先級的操作符時也會起作用。如果方法結(jié)束于:,它們就被自右向左分組;反過來,就是自左向右分組。例如,a ::: b ::: c會被當(dāng)作a ::: (b ::: c)。而a * b * c被當(dāng)作(a * b) * c。
操作符優(yōu)先級也是Scala語言的一部分。你不用怕它。但無論如何,使用括號去厘清什么操作符作用在哪個表達(dá)式上都是好的風(fēng)格?;蛟S你唯一可以確信其他人不用查書就知道的優(yōu)先級關(guān)系就是乘除法操作符(*,/和%),比加減法(+和-)的要高。因此即使a + b << c不用括號也能產(chǎn)生你想要的結(jié)果,寫成(a + b) << c而得到的簡潔性也可能會減少你的同事為了表示不滿在操作符注釋里寫你名字的頻率,“bills!*&^%~code!” 到目前為止,你應(yīng)該能指出給出的這段代碼,Scala編譯器會調(diào)用成(bills.!*&^%~(code)).!()。
【相關(guān)閱讀】
- Scala對象的相等性比較
- Scala的數(shù)學(xué)運算、關(guān)系和邏輯操作及位操作符
- Scala的操作符:任何方法都可以是操作符
- Scala的基本類型及文本化
- Scala程序及其Application特質(zhì)