程式扎記: [Scala 小學堂] Scala Gossic : 起步走 - 資料、變數、操作 (操作順序與關聯)

標籤

2016年4月11日 星期一

[Scala 小學堂] Scala Gossic : 起步走 - 資料、變數、操作 (操作順序與關聯)

轉載自 這裡 
前言 : 
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. 從一些簡單的語法開始,了解 Scala 的許多特性,所以就算是起步走,東西也夠多了. 簡單的小程式可以使用 scala 指令,編譯的事就交給 scalac,編譯想快點就用 fsc. (Scala 官網), 所有的東西都是物件,所有的操作都是方法. 

操作順序與關聯 : 
+、 -、*、/... 這些一般語言所謂的運算子,在 Scala 中其實是方法定義,如果一個運算式中混合了多個「運算子」,那麼該如何決定其優先順序呢?又或者 說,如何決定該呼叫哪個物件的哪個方法?例如 1 + 2 * 3,如何能決定為 (1).+((2).*(3)) ?而不是 ((1).+(2)).*(3) ? Scala 主要是由方法名稱的第一個字元來決定運算的順序,如果方法名稱的第一個字元是 *,則它比 + 有更高的優先順序,以下是方法第一個字元的優先順序 (由高而低),同一列表示優先順序相同 : 
除了以下字元外的其它特殊字元 
*、/、%
+、:
=、!
<、>
&

|
字母
指定運算(非=、<=、>=、==,且以=結尾方法)

所以運算符號一定優先於字母名稱的方法,例如 1 + 2 equals 3,結果就是 (1 + 2) equals 3。指定運算是 +=、-=、*= 、/= 等以 =結 尾,但又不是 =、<=、 >=、== 的運算方法,指定運算優先順序最低,所以 a *= 1 + 4,結果會是 a *= (1 + 4)。當然,最簡單的方式,還是使用括號來釐清優先順序. 當優先順序相同時,基本上由左至右進行運算,所以若 1 + 2 + 3 時,運算的順序是 (1 + 2) + 3,+ 號是左邊物件的方法,運算方法到底屬於哪個物件,這稱之為「關聯性」(Associativity)。一般情況下,運算方法都是屬於左邊物件,不過,當方法名稱是以 : 結尾時, 則該名稱會是右運算元的方法。在 Scala 中的例子是 List 的 ::,它用來在 List「前端」附加物件,例如 : 
scala> val x = List(1, 2)
x: List[Int] = List(1, 2)

scala> println(0::x)
List(0, 1, 2)

但 0 是個 Int,並沒有定義 :: 方法(就算是隱式轉換後的 RichInt 類別也沒有定義 :: 方法),這個操作是如何完成的?答案是 :: 是右邊物件的 方法,也就是 x 所參考的 ListList 物件上的方法,所以上面這個程式,等同於 : 
scala> println(x.::(0))
List(0, 1, 2)

這個程式顯示的結果也是 List(0, 1, 2)。如果你這麼寫,則程式會出錯 : 

由於 :: 以 : 結尾,所以 Scala 會認為要由右邊物件來呼叫 :: 方法,但 3 是個 Int,不會有 :: 方法,所以會出現「value :: is not a member of Int」的錯誤訊息. 由於 : 結尾的方法會被 Scala 視為右邊物件的方法,所以如果是 -1 :: 0 :: x,實際上的運算順序會是反過來從右至左,也就是 (-1 :: (0 :: x)). 由於在 Scala 中,任何的方法都可以撰寫運算子的形式,當你嘗試定義自己的「運算子」時,就必須注意操作的優先順序與關聯性 (也許像是 Array 的 /: 這樣的方法) . 

補充說明 :

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!