前言 :
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. 從一些簡單的語法開始,了解 Scala 的許多特性,所以就算是起步走,東西也夠多了. 簡單的小程式可以使用 scala 指令,編譯的事就交給 scalac,編譯想快點就用 fsc. (Scala 官網), 在變與不變之間,先體會 Scala 更多特性.
Array :
在 Scala 中,如果要建立陣列,可以使用 Array 類別,建立陣列時,須指定陣列後存放的元素型態. 如以下建立長度為 5,內含Int、Double、Boolean、String等指定型態的陣列 :
在建立陣列之後,如果內含元素是整數,則預設值為 0,浮點數則預設值為 0.0,字元則預設值為空字元(字元編碼為0的字元),布林值預設為 false,其它型態則預設值為 null(與 Java 的陣列類似). 如果要多維陣列,基本上是以一維陣列來摸擬,例如要建立二維陣列 :
如果要存取陣列,必須指定陣列索引,與其它語言存取陣列慣例不同的是,在 Scala 中,指定陣列索引時是使用 () 而非 [],例如 :
事實上,當你使用 arr(0) = 10 這樣的指定方式時,Scala 會將之轉換為呼叫陣列的 update() 方法,而你用 arr(0) 的方式要取得指定索引的元素時,Scala 會將之轉換為呼叫 apply 方法。以下是個簡單的驗證方式 :
在 Scala 中,指定索引進行存取時使用 () 而不是 [],其實是為了語法的一致性。這種在 () 中指定索引進行存取的方式,並非只有陣列專屬,只要是有提供 update() 或 apply() 方法的物件,其實都可以使用這樣的存取方式,像是在 String 也曾經使用過這樣的方式 :
- val str = "Scala"
- println(str(0)) // 顯示 'S'
- println(str(1)) // 顯示 'c'
- println(str(2)) // 顯示 'a'
- println(str(3)) // 顯示 'l'
- println(str(4)) // 顯示 'a'
其實在 單例物件 中有介紹過了,Array(10, 20, 30) 這樣的寫法是個語法蜜糖,Scala 會將之轉換為呼叫 scala.Array 伴侶物件的 apply 方法,這個方法會傳回含指定元素的陣列。以下這個程式可以驗證這個說法 :
上面這個範例程式,同時示範了迭代陣列的另一種方式,每一次迭代,都會將 arr 的元素取出指定給i。事實上,陣列提供 foreach 方法可以使用,上面的程式你可以這麼撰寫 :
在 簡單的函式 中有介紹過,foreach中是函式字面寫法,執行時期會傳入函式物件,每次取出一個元素,就會呼叫函式物件。你可以利用類型推斷,讓這個範例更簡短一些 :
arr.foreach(i => println(i)) 其實是 arr.foreach((i) => println(i)) 簡寫,因為只有一個參數,所以括號可以省略。事實上,就上面這個例子來說,最簡短的寫法是 :
事實上,foreach 中是 部份套用函式(Partially applied function)的寫法,這之後還會詳述. 像 foreach 這種傳入函式物件執行某個操作的作法,在 Scala 相當常見。例如陣列的 filter 方法,可以傳入一個會運算出布林值的函式物件,根據真或假決定結果要包括哪些元素,例如 :
事實上,上面這個程式可以使用佔位字元語法(Placeholder syntax)撰寫為以下的方式 :
_ 作為佔位字元,就目前來說,你可以將看它看作是填充欄位,每一次取得的元素值將值入這個欄位(其實完整的語法應該是 (_ : Int) > 30,不過由於利用了類型推斷,所以可以推斷出_應該是 Int,因此可以寫為 _ > 30,佔位字元語言之後還會詳述).
類似地,如果你不僅是想過濾,還想對元素作某些運算後傳回的話,則可以使用 map 方法,例如將每個元素加 1 後傳回新陣列 :
陣列可以串接,不過不是使用 +,而是使用 ++(這是 Array 上定義的方法),這會將兩個陣列的元素取出,建立一個新陣列後傳回。例如 :
如果你要比較兩個陣列的內含值是否相同,由於要逐一比對陣列中每個陣列的元素物件內含值,所以不能直接使用 == 比較,而要使用 deepEquals 方法。例如 :
Supplement
* Tutorialspoint - Scala Arrays
沒有留言:
張貼留言