在 Java 我們在 method 的定義中,要 return 一個值,需要使用 return 這個 keyword。
在 Scala,除可使用 return keyword 來作為 method 的 return 值外,也可使用 method 最後一個執行到的 statement 作為整個 method 的 return 值。這樣的方式,在許多的語言中出現。
Scala 鼓勵使用最後一個執行 statement 的值為 return 值,而不鼓勵使用 return。不鼓勵的原因在於 Scala 引進函數式的觀念。
在函數式的語言中,對於破壞整個流程的結構(construct)非常不歡迎,因為這隱含你需要一個一個 statement 循序走下去,才知道何時跳開原有流程。
我們習慣在程式中,把某一變數與某個值比較,再視不同的值走不同的程式路徑。這種方式,函數式語言是不歡迎的,因為整個函數邏輯被分割成多塊。而 return 這種忽然由某一個 statement 中直接跳出 method 的作法,是函數式語言不能忍受的,因此 Scala建議你不要使用這種方式。
同樣的原因,break 與 continue 這兩個在 Java loop 中常用到的 statement,也完全不符合函數式語言的概念。
Scala 建議大家盡量少用 loop 來製作程式(你應該盡量使用 iteration 與 recursion來取代 loop), break 與 continue 這兩個突兀式脫離迴圈的方式,會加深 loop 誤用的程度,是 Scala 所要改革的對,因此在 Scala 中已遭移除,你應該注意。
既然移除 break / continue,以相同的邏輯,Scala 應該一併把 return 移除,但 Scala 只是建議你不要使用,可見 return 的影響力。相信 Martin 的團隊針對 return 是否移除,一定有過相當多的激辯。
2011年4月29日 星期五
3-9. Assignment的 result 值
之前說到,在 Scala 中每個 statement 都有 result 值,這也包含 assignment。
但請注意,Scala中,assignment 的 result 型態是 Unit型態,result value 為 unit value,並非是右值(right-hand-side value),這與一般人的想像不同,請小心。
請看下例

第一個指令宣告變數 n。
第二個指令,使用 assignment 設定 n=20,並印出 result 值。由 output 可以看到 result 值為 (),是Unit type。
我們可能犯以下的錯誤,連續的 variable assignment,誤以為值會傳遞過來。如:
我們看實際的案例
但請注意,Scala中,assignment 的 result 型態是 Unit型態,result value 為 unit value,並非是右值(right-hand-side value),這與一般人的想像不同,請小心。
請看下例

第一個指令宣告變數 n。
第二個指令,使用 assignment 設定 n=20,並印出 result 值。由 output 可以看到 result 值為 (),是Unit type。
我們可能犯以下的錯誤,連續的 variable assignment,誤以為值會傳遞過來。如:
n1 = n2 = 100上面的指令,我們可能會以為n1, n2 的值都會是 100,其實不是,n1 會被設定為 ()。
我們看實際的案例

3-8. Unit 型態
Uni t型態是一個特殊的型態,起源於 tuple(多個值的型態)。
tuple 是一個重要的東西,我們未來會詳加介紹。這裡簡單說明,tuple 使用簡單的小括號將各個值放在一起,是一種非常有用的資料結構。
A. 一個資料的tuple,如 (1) *附註
B. 兩個資料的tuple,如 (1, "A")
tuple 是一個重要的東西,我們未來會詳加介紹。這裡簡單說明,tuple 使用簡單的小括號將各個值放在一起,是一種非常有用的資料結構。
A. 一個資料的tuple,如 (1) *附註
B. 兩個資料的tuple,如 (1, "A")
C. (1, 2, "A", 5.0) 是一個 4 值的 tuple。
tuple 可用來放多個值,但 tuple-0 表示什麼?
tuple-0 只可有一個值,就是空的 tuple,即 ()。
這個 tuple-0 的型態在 Scala 把它特別表明出來,稱為 Unit 型態。Unit型態,只有一個instance,稱為 unit value,即 ()。
為何需要特別標明出來呢?原因是要用他來表明特別的東西。
之前提到,所有的 statement 都需要有 result 值,這包含 method,但若是 method 真的沒有 return 值呢?這時就把它表明為 return 回「空資料的 tuple」,這就是 Unit。
因此如果 method 沒有 return 值,在 Scala 的意義就是該 method 的 return type為 Unit,return 值為()。
因此如果 method 沒有 return 值,在 Scala 的意義就是該 method 的 return type為 Unit,return 值為()。
當 Java 與 Scala 混用時, Java 中 void 型態的 method,在 Scala 會變成該 method return type 為 Unit。
附註:因為一個資料的 tuple,小括號會被解釋運算,所以 (1) 會被視為 1 這個 Int,而非 Tuple (Int),若確定要使用一個值的 Tuple,需要使用 Tuple1(1)
2011年4月24日 星期日
3-7. statement 的 result 值
在不同的程式語言,對於 statement 的 result 值定義不太相同。有些語言的某些 statement 可以沒有 result 值,比如 while loop 可能就沒有 result 值。
「那在 Scala 中的情況呢?」
Scala 的情況是,「所有的 statement 或 expression 都有 result 值」,沒有任何例外,包含不需 return 回任何東西的 method,也都有 result 值。
各個 statement 的 result 值有相關的規定,這包含 method 呼叫與 assignment。我們後續會特別針對 method 與 assignment 做討論。
「那在 Scala 中的情況呢?」
Scala 的情況是,「所有的 statement 或 expression 都有 result 值」,沒有任何例外,包含不需 return 回任何東西的 method,也都有 result 值。
各個 statement 的 result 值有相關的規定,這包含 method 呼叫與 assignment。我們後續會特別針對 method 與 assignment 做討論。
3-6. 型態推論(Type Inference)
型態推論是一個很重要的概念,可以讓 programmer 大幅減少程式的撰寫,就如同使用動態型態的方便性。
型態推論可不是Scala所發明,早在以前,一些函數式語言與一些命令式語言都已經出現型態推論。千萬不要以為 Scala 這麼神勇,什麼東西都開創新局,其實它只是參考很多好的觀念,把它加到自己的語言設計中罷了。
支援Type Inference的語言包含(參考wiki http://en.wikipedia.org/wiki/Type_inference)
1. Visual Basic:9.0開始
2. C#:3.0開始
3. Clean
4. Haskell
5. ML
6. OCaml
7. Scala
很多吧!這也突顯出Type Inference的重要性。
可還記得之前的討論,為了要加速開發,以及爭取 Script 的使用者,Scala 想要能夠有 Dynamic Type 的便利性,以及 Static Type 的嚴謹度(嚴謹可以讓 compiler 幫你多做一點事,及早檢查出程式的問題,增加程式的品質),這時型態推論就派上用場。
所謂型態推論是 compiler 可以幫忙推論出型態的地方,你就可以省略指明型態。
「這是什麼意思?」
讓我們回到宣告變數的範例:
如果我們的想法是「現在宣告的變數,與右值(right-hand-side)的型態相同」,我們就可以大膽讓 compiler 幫我們代勞,推論出該變數應該具有的型態。這樣的推論代勞就叫型態推論(Type Inference)。
這種方式是不是很方便,是否有點像使用 Dynamic Type 語言的作法!
其實,type inference 更有用的地方在於 function(或稱method)的 return 型態。
在 Java,每個 method 都需要有 return 的型態,就算沒有 return 型態,你也要指明它是 void。void 可以把它看成是一種特殊的型態,表示不 return 值。
在 Scala,method 一定有 return 型態的堅持仍在,Scala 中每個 method 都需要有 return 型態。但我們在 Scala 中宣告 method,卻通常省略宣告 method 的 return 型態,讓我們的程式看起來更簡潔易懂。我們會希望 compiler 使用型態推論幫忙找出 method 的 return 型態。
method 我們尚未討論,這裡我們先舉個小例,說明型態推論在 method 中的情況。
Scala 使用 method 最後一個執行到的 statement 的值作為整個 method 的 return 值。f1 的 return 值很清楚是 n + 100。因為 n + 100 的型態為 Int,所以 f1 的 return 型態推論出是 Int。
型態推論雖然方便,但注意不要任意延伸!
「嗯,那我瞭解了,型態推論很方便,所以 method 的參數也可以推論吧?」
以上就是任意延伸的案例,雖然上述的推論看起來沒有問題(其實還是有問題,n 可能是其他型態,但具有 + 的 method),但在 Scala 中參數是不可以被推論的!method 的一定要明確說明型態,否則 compiler 會有 error。
關於型態推論,結論是
1. 變數可以推論
2. method 的 return type 可以推論
3. method 參數不可推論
參數型態推論是一個容易犯的錯誤,另一個典型的型態推論錯誤延伸是「型態轉換」,我們先看例子
「奇怪,不是會推論嗎? n 在第二個 statement 變成 Float 就好了啊?」
錯誤的原因不是推論的問題,而是搞錯靜態語言的特性。
所謂靜態語言是變數的型態一旦決定後,就不會改變的,這叫靜態語言。
以靜態語言而言,第二個 statement 的意思是要把一個浮點數的值,設定給一個 Int 型態的變數,你說,此時 compiler 會如何做?當然就是告訴你 type mismatch。
請大家不要混淆了 variable initialize 與 variable value assignment。
1. Variable initialize 發生在變數宣告時,Scala 要求變數宣告時需要設定初值,變數宣告時,也需要決定該變數的型態,因此可以使用型態推論。
2.Variable value assignment 是變數宣告之後,重新設定新值,因為變數早在宣告時就已固定型態,這時沒有所謂的型態推論。使用不同的型態設定給變數,隱含型態轉變,compiler 自然不會允許。
「奇怪?可是很多 Script 語言中可以這樣做啊?」
沒錯,比如在 JavaScript 中你確實是可以這樣做。
原因是在於這些 Script 語言使用動態型別,而且有些還支援動態轉換(如把 String 轉成對應的數值資料),所以當你執行第二個 statement 時,script engine會以為你要重新設定 n 的型態,可以馬上幫你轉換。
Scala 是靜態型別的語言,不允許你重新設定變數的型態,當你要將 10.5 指定給 n 時,會以為你型態搞錯了,自然給你一個錯誤。
型態推論雖然好用,但不能有過度的期待,Scala 還是堅守 Static Type 的界線,自動轉換(比如型別的轉換,如 Int 轉成 String,或是 String 轉成 Int)不是可以使用型態推論做到的。
若需要型態的轉換(比如讓用戶輸入一個數值的字串,程式要由字串轉成對應的值),此時仍然需要 explicit 指出,或是使用未來介紹的 implicit conversion 機制才可解決。
型態推論可不是Scala所發明,早在以前,一些函數式語言與一些命令式語言都已經出現型態推論。千萬不要以為 Scala 這麼神勇,什麼東西都開創新局,其實它只是參考很多好的觀念,把它加到自己的語言設計中罷了。
支援Type Inference的語言包含(參考wiki http://en.wikipedia.org/wiki/Type_inference)
1. Visual Basic:9.0開始
2. C#:3.0開始
3. Clean
4. Haskell
5. ML
6. OCaml
7. Scala
很多吧!這也突顯出Type Inference的重要性。
可還記得之前的討論,為了要加速開發,以及爭取 Script 的使用者,Scala 想要能夠有 Dynamic Type 的便利性,以及 Static Type 的嚴謹度(嚴謹可以讓 compiler 幫你多做一點事,及早檢查出程式的問題,增加程式的品質),這時型態推論就派上用場。
所謂型態推論是 compiler 可以幫忙推論出型態的地方,你就可以省略指明型態。
「這是什麼意思?」
讓我們回到宣告變數的範例:
var n = 10right hand side 的值10,我們很清楚 10 是一個 Int 的型態,由於「不同型態的兩個變數或值是不可互相指定的」,所以我們知道上述 statement 的 n 應該是 Int 型態(當然也有可能是 Int 的 parent class)。這樣的推論,對 compiler 也不會有太大的困難,很容易幫我們代勞。
如果我們的想法是「現在宣告的變數,與右值(right-hand-side)的型態相同」,我們就可以大膽讓 compiler 幫我們代勞,推論出該變數應該具有的型態。這樣的推論代勞就叫型態推論(Type Inference)。
這種方式是不是很方便,是否有點像使用 Dynamic Type 語言的作法!
其實,type inference 更有用的地方在於 function(或稱method)的 return 型態。
在 Java,每個 method 都需要有 return 的型態,就算沒有 return 型態,你也要指明它是 void。void 可以把它看成是一種特殊的型態,表示不 return 值。
在 Scala,method 一定有 return 型態的堅持仍在,Scala 中每個 method 都需要有 return 型態。但我們在 Scala 中宣告 method,卻通常省略宣告 method 的 return 型態,讓我們的程式看起來更簡潔易懂。我們會希望 compiler 使用型態推論幫忙找出 method 的 return 型態。
method 我們尚未討論,這裡我們先舉個小例,說明型態推論在 method 中的情況。
def f1(n: Int) = { n + 100 }上例我們定義一個 method f1,我們沒有指明 return type,但 compiler 會幫我們找出來。
Scala 使用 method 最後一個執行到的 statement 的值作為整個 method 的 return 值。f1 的 return 值很清楚是 n + 100。因為 n + 100 的型態為 Int,所以 f1 的 return 型態推論出是 Int。
型態推論雖然方便,但注意不要任意延伸!
「嗯,那我瞭解了,型態推論很方便,所以 method 的參數也可以推論吧?」
def f1(n) = {n+100}因為 n + 100,所以 n 唯一的可能型態是 Int,compiler可以幫我自動推論 n 的型態,這樣又可以少打幾個字。
以上就是任意延伸的案例,雖然上述的推論看起來沒有問題(其實還是有問題,n 可能是其他型態,但具有 + 的 method),但在 Scala 中參數是不可以被推論的!method 的一定要明確說明型態,否則 compiler 會有 error。
關於型態推論,結論是
1. 變數可以推論
2. method 的 return type 可以推論
3. method 參數不可推論
參數型態推論是一個容易犯的錯誤,另一個典型的型態推論錯誤延伸是「型態轉換」,我們先看例子
var n = 10 n = 10.5第二個 statement 會 compile 錯誤!
「奇怪,不是會推論嗎? n 在第二個 statement 變成 Float 就好了啊?」
錯誤的原因不是推論的問題,而是搞錯靜態語言的特性。
所謂靜態語言是變數的型態一旦決定後,就不會改變的,這叫靜態語言。
以靜態語言而言,第二個 statement 的意思是要把一個浮點數的值,設定給一個 Int 型態的變數,你說,此時 compiler 會如何做?當然就是告訴你 type mismatch。
請大家不要混淆了 variable initialize 與 variable value assignment。
1. Variable initialize 發生在變數宣告時,Scala 要求變數宣告時需要設定初值,變數宣告時,也需要決定該變數的型態,因此可以使用型態推論。
2.Variable value assignment 是變數宣告之後,重新設定新值,因為變數早在宣告時就已固定型態,這時沒有所謂的型態推論。使用不同的型態設定給變數,隱含型態轉變,compiler 自然不會允許。
「奇怪?可是很多 Script 語言中可以這樣做啊?」
沒錯,比如在 JavaScript 中你確實是可以這樣做。
原因是在於這些 Script 語言使用動態型別,而且有些還支援動態轉換(如把 String 轉成對應的數值資料),所以當你執行第二個 statement 時,script engine會以為你要重新設定 n 的型態,可以馬上幫你轉換。
Scala 是靜態型別的語言,不允許你重新設定變數的型態,當你要將 10.5 指定給 n 時,會以為你型態搞錯了,自然給你一個錯誤。
型態推論雖然好用,但不能有過度的期待,Scala 還是堅守 Static Type 的界線,自動轉換(比如型別的轉換,如 Int 轉成 String,或是 String 轉成 Int)不是可以使用型態推論做到的。
若需要型態的轉換(比如讓用戶輸入一個數值的字串,程式要由字串轉成對應的值),此時仍然需要 explicit 指出,或是使用未來介紹的 implicit conversion 機制才可解決。
2011年4月23日 星期六
3-5. 常數 / 變數 與 mutable / Immutable
之前我們曾提及 val 與 var,val 大約可比擬其他語言的 const。
val 在 Scala 非常被強調,盡量可以使用 val 的地方,請盡量使用。
接觸過函數式語言的洗禮後,你應該知道 Scala 是不喜歡變數這種東西的,因為不管是為了支援 concurrency,或是降低副作用(Side-Effect),使用變數都不是一種好習慣。
這個原則在你平常的程式撰寫也是同樣,就算你不使用 Scala,也應謹守「盡量不使用變數」的原則。「用修改變數值來作為控制程式的手段」這個習慣真的不好,儘快改變掉這習慣,對你在學習 Scala,或撰寫好的程式都會有很大的幫助。
除了 val 外,還有一個看起來很類似的東西,Immutable Data Type。
所謂 Immutable Data Type,就是這個 Data Type裡面的 field不能被更改。Mutable的英文字是可更改的,Immutable 的意思就是不可更改的。
所謂 Immutable 就是不能被更改,表示一旦設定值(其實應該叫被 initial 值之後),以後不能被改變。
「這個 Immutable 好像和 val 一樣啊?為何有了 val 又要有 Immutable?」
不,val 與 Immutable 是不相同的東西。
我們首先釐清一個觀念,在 Java 中所有的 object (或 Scala 中,大部分的 object)都是 reference type。reference type 的意思是,變數只儲存一個 reference 到真正儲存資料的記憶體,變數並非擁有真正的資料。我們姑且可以把 reference type 當成一個 pointer,也就是, Java 的 object 變數,只是一個 pointer,point到真正的資料。
val 指的是「該變數(或叫該常數好了)不能再被變動」。所以 val 的變數不能被重新 assign 新的值,但並沒有限定被指定到的地方不能該新值。
讓我們舉例說明
第三個 statement 可以正常工作,你看出問題了嗎?
沒錯,雖然 p1 是 val,但 p1 可以變動 name 欄位。若有兩個 thread,一個讀取 p1.name,一個更改 p1.name,不是有可能產生 race condition 嗎?
確實沒錯,所以才會有 Immutable Data Type 這個東西, Immutable Data Type 表示該值不能該動,也就是不希望透過變數更改到欄位值。
「有沒有實例呢?」
有,其實你也用過, Java裡面的 String,就是一個 Immutable 的 data type。讓我們看例子
最後 statemenet 要印出 s2,結果會是"A"。
原因在於第三個 statement,雖然更改了 s1 的指向指到 "B",但此時 s2 並沒有改變,仍舊指到舊的 "A",所以印出 "A"。
String 這個 class 的 instance 一旦被 create 之後,instance 裡面的值就不可被改變,雖然 s1 更改了,但此時系統會重新 create 一個新的 String instance 給 s1,此時 s2 所指的 instance 完全沒有更改。
到此,我們應該很清楚
1. val 所訂定的是變數本身,說明的是,該變數不能被 reassign。
2. Immutable 指的是,所指到的資料結構不能被更改。
val 與 immutable 兩者所訂定的對象不同。若要完整支援 concurrency,val 配上 immutable 是最合適的。
「除 String 外,還有什麼東西是 Immutable?」
其實,Scala 幫大家準備好了。我們常用的資料結構,List、Set、Map,在 Scala 世界都有兩份,一份是 mutable,另一份是 immutable,供大家使用。
使用 mutable 的版本,就和在 Java 的使用情況相同,允許我們在同一個 instance 中增加、修改、或減少該 instance 的資料。使用這種版本,在 multi-thread 的情況下,programmer 需要自行掌握資料的完整性 (data consistence)。
使用 immutable 的版本,instance 一旦 initial 完畢,該 instance 的資料就不會再被改變。如果呼叫該 instance 的 add 或 delete 等修改資料的 method,系統會 create 一個新的 instance,並把原來 instance 資料 copy 一份過來,然後做修改,最後返回這個新的 instance。
「create 一個新的 instance,並把原來 instance 資料 copy 一份過來,然後做修改」,這幾個動作在新的 instance 初始資料時一次完成。當修改資料的 method 完成時,所使用到的資料結構已經是完全新的,舊的資料結構完全沒有被更動到。
舉例說明,若有兩個變數 x1, x2 指到同一個 immutable 資料 d1,其中變數 x2 呼叫修改資料 d1 的 method m(),此時系統的執行狀況如下
1. 產生一個新的 immutable 資料 d2,d2 的初始值使用 d1,以及 method m()
2. 讓 x2 指到新的資料 d2
3. d1 沒有任何改變,x1 也沒有任何改變,仍然是指到 d1
由上述的動作,我們可以瞭解 x1 並沒有變化,x2 的改變只改變到它自己的部份。所以就算 x1 與 x2 在不同的 thread,彼此也不會互相影響,不會有 race condition 的情況發生,這對撰寫concurrency 程式是一大保障。
Immutable 的資料結構帶來程式穩定的保證,但它的代價是「當修改的 method 呼叫時,重新複製一份資料的記憶體浪費,以及複製的時間」。
Mutable 與 immutable 這兩種版本, Scala 的 default 使用 immutable 版本。請不用擔心無法使用 mutable 版本,Scala 這裡的 default 表示你不特別加以指定時會使用 immutable。你隨時可以使用 mutable 版本,甚至在同一個 class 中使用兩個不同版本的資料結構,一個是 mutable 另一個是immutable。
val 在 Scala 中非常被強調, immutable 也被同樣強調,主要原因是要讓開發 concurrency 程式不再是那麼痛苦的事。
val 在 Scala 非常被強調,盡量可以使用 val 的地方,請盡量使用。
接觸過函數式語言的洗禮後,你應該知道 Scala 是不喜歡變數這種東西的,因為不管是為了支援 concurrency,或是降低副作用(Side-Effect),使用變數都不是一種好習慣。
這個原則在你平常的程式撰寫也是同樣,就算你不使用 Scala,也應謹守「盡量不使用變數」的原則。「用修改變數值來作為控制程式的手段」這個習慣真的不好,儘快改變掉這習慣,對你在學習 Scala,或撰寫好的程式都會有很大的幫助。
除了 val 外,還有一個看起來很類似的東西,Immutable Data Type。
所謂 Immutable Data Type,就是這個 Data Type裡面的 field不能被更改。Mutable的英文字是可更改的,Immutable 的意思就是不可更改的。
所謂 Immutable 就是不能被更改,表示一旦設定值(其實應該叫被 initial 值之後),以後不能被改變。
「這個 Immutable 好像和 val 一樣啊?為何有了 val 又要有 Immutable?」
不,val 與 Immutable 是不相同的東西。
我們首先釐清一個觀念,在 Java 中所有的 object (或 Scala 中,大部分的 object)都是 reference type。reference type 的意思是,變數只儲存一個 reference 到真正儲存資料的記憶體,變數並非擁有真正的資料。我們姑且可以把 reference type 當成一個 pointer,也就是, Java 的 object 變數,只是一個 pointer,point到真正的資料。
val 指的是「該變數(或叫該常數好了)不能再被變動」。所以 val 的變數不能被重新 assign 新的值,但並沒有限定被指定到的地方不能該新值。
讓我們舉例說明
class People(name: String) // 宣告一個 class 叫 People,有一個 name 的 data field。現在可能暫時有點看不懂,請先跳過一下 val p1 = new People("John") // 產生一個 People instance,他的 name 叫 John,注意 p1 是 val (常數) p1.name = "Jason" // 修改 p1.name,這是正確的,雖然 p1 是 val p1 = new People("Jason") // 重新 assign 一個 object 給 p1,但由於 p1 是 val,所以 compiler 出現錯誤
第三個 statement 可以正常工作,你看出問題了嗎?
沒錯,雖然 p1 是 val,但 p1 可以變動 name 欄位。若有兩個 thread,一個讀取 p1.name,一個更改 p1.name,不是有可能產生 race condition 嗎?
確實沒錯,所以才會有 Immutable Data Type 這個東西, Immutable Data Type 表示該值不能該動,也就是不希望透過變數更改到欄位值。
「有沒有實例呢?」
有,其實你也用過, Java裡面的 String,就是一個 Immutable 的 data type。讓我們看例子
var s1 = "A" //設定 s1 為 "A" 字串 var s2 = s1 //設定 s2 指到 s1,s1, s2 此時都指到 "A" 字串 s1 = "B" //設定 s1 為 "B" 字串 println(s2) // 這裡會印出 "A"上述的 statements 是正確的。
最後 statemenet 要印出 s2,結果會是"A"。
原因在於第三個 statement,雖然更改了 s1 的指向指到 "B",但此時 s2 並沒有改變,仍舊指到舊的 "A",所以印出 "A"。
String 這個 class 的 instance 一旦被 create 之後,instance 裡面的值就不可被改變,雖然 s1 更改了,但此時系統會重新 create 一個新的 String instance 給 s1,此時 s2 所指的 instance 完全沒有更改。
到此,我們應該很清楚
1. val 所訂定的是變數本身,說明的是,該變數不能被 reassign。
2. Immutable 指的是,所指到的資料結構不能被更改。
val 與 immutable 兩者所訂定的對象不同。若要完整支援 concurrency,val 配上 immutable 是最合適的。
「除 String 外,還有什麼東西是 Immutable?」
其實,Scala 幫大家準備好了。我們常用的資料結構,List、Set、Map,在 Scala 世界都有兩份,一份是 mutable,另一份是 immutable,供大家使用。
使用 mutable 的版本,就和在 Java 的使用情況相同,允許我們在同一個 instance 中增加、修改、或減少該 instance 的資料。使用這種版本,在 multi-thread 的情況下,programmer 需要自行掌握資料的完整性 (data consistence)。
使用 immutable 的版本,instance 一旦 initial 完畢,該 instance 的資料就不會再被改變。如果呼叫該 instance 的 add 或 delete 等修改資料的 method,系統會 create 一個新的 instance,並把原來 instance 資料 copy 一份過來,然後做修改,最後返回這個新的 instance。
「create 一個新的 instance,並把原來 instance 資料 copy 一份過來,然後做修改」,這幾個動作在新的 instance 初始資料時一次完成。當修改資料的 method 完成時,所使用到的資料結構已經是完全新的,舊的資料結構完全沒有被更動到。
舉例說明,若有兩個變數 x1, x2 指到同一個 immutable 資料 d1,其中變數 x2 呼叫修改資料 d1 的 method m(),此時系統的執行狀況如下
1. 產生一個新的 immutable 資料 d2,d2 的初始值使用 d1,以及 method m()
2. 讓 x2 指到新的資料 d2
3. d1 沒有任何改變,x1 也沒有任何改變,仍然是指到 d1
由上述的動作,我們可以瞭解 x1 並沒有變化,x2 的改變只改變到它自己的部份。所以就算 x1 與 x2 在不同的 thread,彼此也不會互相影響,不會有 race condition 的情況發生,這對撰寫concurrency 程式是一大保障。
Immutable 的資料結構帶來程式穩定的保證,但它的代價是「當修改的 method 呼叫時,重新複製一份資料的記憶體浪費,以及複製的時間」。
Mutable 與 immutable 這兩種版本, Scala 的 default 使用 immutable 版本。請不用擔心無法使用 mutable 版本,Scala 這裡的 default 表示你不特別加以指定時會使用 immutable。你隨時可以使用 mutable 版本,甚至在同一個 class 中使用兩個不同版本的資料結構,一個是 mutable 另一個是immutable。
val 在 Scala 中非常被強調, immutable 也被同樣強調,主要原因是要讓開發 concurrency 程式不再是那麼痛苦的事。
3-4. Local Variable 宣告
var / val 除了可用來宣告 data field,也可用來宣告 local variable。
Local variable 的宣告方式與在 Java 的相同,不同的 scope 可以有相同名稱的變數。
以下為不同 scope 中,相同名稱的變數的宣告方式。
Local variable 的宣告方式與在 Java 的相同,不同的 scope 可以有相同名稱的變數。
以下為不同 scope 中,相同名稱的變數的宣告方式。
class S { var n: Int = 0 // data member override def print = { var n = 10 // method print() 的 local variable for (i <- 1 to 10) { var n = 100 // loop 裡面的 local variable println("i + n = " + (i + n)) } } }
3-3. 變數宣告與重新設定值
Scala 與 Java 相同,都是強型態的語言,而且沒有宣告變數,不能使用該變數。
宣告變數,Java 使用的格式是
var_name: type;
記得分號 「;」 是 Java statement 的分隔符號,不可省略。
例:
在 Scala 中宣告一個變數,格式為
var var_name: type;
var 是 Scala 的 keyword,表示要開始宣告變數,後面接變數名稱,再接 type。type 後面的分號,可以省略。
例:
Scala 在這裡有許多與 Java 不同的地方:
A.分號:
在 Scala 中,為符合快速開發的原則,可以省略的,都省略了,所以10後面的分號是可以省略的。省略分號的原則,四處都適用,但你若不喜歡省略,也是可以繼續使用。
B.初始值:
在 Java 變數的宣告,初始值是可有可無的,這可分為兩種狀況:
1. 當宣告的變數是 method 裡面的 local variable 時,Java 不會強迫你一定要指定初始值。但若你尚未指定值,就使用到該變數,compiler 不會允許這種情況,會在你使用該 variable 的地方產生 error,要求你在變數被使用之前設定該變數值。
2. 當宣告的變數是 class 中的 data field 時,每個 data field 都需要有初始值。只是你若沒有特別指定,javac 會幫你加上 default 的初始值,這些初始值如下:
所謂的預定初始值,是使用系統預定的初始值,這有點像 Java 對待 class 中的 data field 一樣。但在 Scala 中,你可要講清楚要使用系統預定的初始值,作法如下:
那個 underscore _ 是 Scala 的「預定萬用字元」,代表的意思就是那個「預定的東西」。
這個預定萬用字元在 Scala 運用的範圍非常廣泛,你以後會很容易看到,我們在其他遇到的地方適時解釋給各位瞭解。
預定萬用字元使用在初始值,所代表的意義就是使用系統的預定值。
系統的預定值依據不同的型態會有不同的預定值,與 Java 類似,數值型態預定值為 0、布林型態預定值為 false、其他的 Reference 型態為 null。(在 Scala中所有的東西都是object,所以這裡特別要說明是 Reference 型態,不可說所有的 object 都會初始為 null)
上述兩個宣告
C.var 與 val:變數與常數
在一般的語言中,我們可以看到有兩種變數,一種真正的變數(可以重新設定值),一種是常數(不可重新設定值)。在 Scala 中支援這兩種,變數使用 var 宣告,常數使用 val 宣告,var 是 variable 的縮寫,val 是 value 的縮寫。
1.var
Scala 宣告 val 的常數,被 compile 出來之後就是一個加上 final modifier 的 variable,也就是在任何地方,該變數都不可再被重新設定值,不論你使用 Scala 或 Java 來存取該常數。
D. 型態推論
型態推論簡單講是,由於 compiler 可以判斷等號的右邊是一個 Int 型態,所以 n1 沒有特別指明哪個型態時,就由 compiler 來自行做型態的推論。型態推論是一個重要的觀念,我們將在以後篇幅中討論。
Scala 最嚴謹的變數宣告是「變數名稱加型態名稱,後面再加上初始值」,但由於分號省略與型態推論,所以可將變數宣告寫的更精簡
如:
1.分號省略:可以變為
2.型態推論(Type Inference):可以變為
「var n1 = 10」 這種宣告方式,反而是最常見的變數宣告方式。
重新設定值:變數宣告完後,你可以重新給它新的值,此時的用法與 Java一模一樣,但 val 常數不可以在重新 assign 值。
宣告變數,Java 使用的格式是
var_name: type;
記得分號 「;」 是 Java statement 的分隔符號,不可省略。
例:
n1: int;
在 Scala 中宣告一個變數,格式為
var var_name: type;
var 是 Scala 的 keyword,表示要開始宣告變數,後面接變數名稱,再接 type。type 後面的分號,可以省略。
例:
var n1: Int = 10
Scala 在這裡有許多與 Java 不同的地方:
A.分號:
在 Scala 中,為符合快速開發的原則,可以省略的,都省略了,所以10後面的分號是可以省略的。省略分號的原則,四處都適用,但你若不喜歡省略,也是可以繼續使用。
B.初始值:
在 Java 變數的宣告,初始值是可有可無的,這可分為兩種狀況:
1. 當宣告的變數是 method 裡面的 local variable 時,Java 不會強迫你一定要指定初始值。但若你尚未指定值,就使用到該變數,compiler 不會允許這種情況,會在你使用該 variable 的地方產生 error,要求你在變數被使用之前設定該變數值。
2. 當宣告的變數是 class 中的 data field 時,每個 data field 都需要有初始值。只是你若沒有特別指定,javac 會幫你加上 default 的初始值,這些初始值如下:
- 數值型態的初始值為 0 或 0.0
- 布林型態的初始值為 false
- Reference型態(在Java中所有的 object 都是 Reference 型態)為 null
所謂的預定初始值,是使用系統預定的初始值,這有點像 Java 對待 class 中的 data field 一樣。但在 Scala 中,你可要講清楚要使用系統預定的初始值,作法如下:
var n1: Int = _ var s1: String = _
那個 underscore _ 是 Scala 的「預定萬用字元」,代表的意思就是那個「預定的東西」。
這個預定萬用字元在 Scala 運用的範圍非常廣泛,你以後會很容易看到,我們在其他遇到的地方適時解釋給各位瞭解。
預定萬用字元使用在初始值,所代表的意義就是使用系統的預定值。
系統的預定值依據不同的型態會有不同的預定值,與 Java 類似,數值型態預定值為 0、布林型態預定值為 false、其他的 Reference 型態為 null。(在 Scala中所有的東西都是object,所以這裡特別要說明是 Reference 型態,不可說所有的 object 都會初始為 null)
上述兩個宣告
var n1: Int = _ // 與 var n1: Int = 0 相同意義 var s1: String = _ // 與 var s1: String = null 相同意義
C.var 與 val:變數與常數
在一般的語言中,我們可以看到有兩種變數,一種真正的變數(可以重新設定值),一種是常數(不可重新設定值)。在 Scala 中支援這兩種,變數使用 var 宣告,常數使用 val 宣告,var 是 variable 的縮寫,val 是 value 的縮寫。
1.var
var n1: Int = 102.val
val n1: Int = 10val宣告的常數指定初始值之後,不可以再被重新設定(就算設定的值一模一樣也不可以)。
Scala 宣告 val 的常數,被 compile 出來之後就是一個加上 final modifier 的 variable,也就是在任何地方,該變數都不可再被重新設定值,不論你使用 Scala 或 Java 來存取該常數。
D. 型態推論
型態推論簡單講是,由於 compiler 可以判斷等號的右邊是一個 Int 型態,所以 n1 沒有特別指明哪個型態時,就由 compiler 來自行做型態的推論。型態推論是一個重要的觀念,我們將在以後篇幅中討論。
var n1 = 10以上例而言,n1 被指定為 Int 型態。
Scala 最嚴謹的變數宣告是「變數名稱加型態名稱,後面再加上初始值」,但由於分號省略與型態推論,所以可將變數宣告寫的更精簡
如:
var n1: Int = 10;
1.分號省略:可以變為
var n1: Int = 10
2.型態推論(Type Inference):可以變為
var n1 = 10
「var n1 = 10」 這種宣告方式,反而是最常見的變數宣告方式。
重新設定值:變數宣告完後,你可以重新給它新的值,此時的用法與 Java一模一樣,但 val 常數不可以在重新 assign 值。
var n = 10 //宣告變數,並給初值 n = 20 // 重新 assign 新的值請注意:n = 20 這個 assignment 的 result value 是 unit value(unit value 以後會討論,現在先把 unit value 看成沒有值),不是 20 這個值。
3-2. 分號省略原則 -- 分號推論
Scala 為了讓程式開發可以加速,以及可以運用在 script 的寫作上面,對於分號「;」的處理原則是能省則省。
分號是 C 語言系列的標準分隔符號,一個 statement 的結束必須以分號為準,並不參考其他的東西(比如分行),這個原則其實很久就受到多方的挑戰,尤其是 script 語言。
我們常見的 script 語言除可使用分號當分隔符號外,大都也可使用分行當分隔符號(如:bash、DOS 的 bat 等)。基於 script 語言強調「簡易、方便」的處理原則,只要想要切入 script 應用的語言,都會考慮分行作為分隔的原則。
例如 JavaScript,他的語法屬於 C 系列(Java 承繼 C 的語法精神、JavaScript 承繼 Java 的語法精神),但 JavaScript 決定分號並不是唯一的分隔符號。在 JavaScript 中你仍然可以使用分號來結束一個 statement ,但只要在允許的範圍內,分號是可有可無的。
何謂允許的範圍?就是「JavaScript Engine 如果可以分辨出一個獨立的 statement」的狀況下,這種狀況最典型的就是分行,因此你若有分行分開兩個 statement,那個分號就已變成可有可無,沒有存在的必要,這時的分號是可以省略的。
Scala 的思想邏輯也是著重在簡單上,希望讓 Programmer 快速開發程式,因此自然有相同省略分號的思考邏輯。
在 Scala 中,只要可以省略分號的地方,你就可以省略,這就是「分號省略原則」。
當然,你若執意要保留分號,以便與 Java 程式碼看起來比較相像,也是可以,只是分號省略是 Scala 比較推薦的方式。
「什麼是只要可以省略分號的地方?」
大部分的 programmer 在一行只會寫下一個 statement,不同的 statement 寫在不同行是絕大多數人的習慣,所以 statement 與 statement 中間通常都會有分行符號,因此預測一個分行代表該行的 statement 的結束是合理的推論。依照這個推論,分行符號通常隱含著一個分號,所以 Scala 把分行當成可以省略分號的地方。
正常情況,Scala 會在行與行之前,偷偷加上分號,所以該行的 statement 會被結束。但下列情況的分行符號,Scala 不會進行偷偷加上分號的動作
1. 該行的命令尚未結束,比如在一個 infix operator 的 statement 中間,或是呼叫某個 object 的 method,但只寫到點「.」這個符號,此時不會自動補上分號。
2. 下一行的 statement 並不是一個正常 statement 的開頭,此時也不會自動在前一行補上分號。
3. 小括號與中括號內部的分行,也不會自動補上分號。
「除以上三點的情況,在一般分行符號加上分號」,這種動作就稱為分號推論「semicolon inference」。
我們來看以下的例子:
我們可以改寫為
有沒有分號,兩者所代表的意義,都一模一樣。
分號是 C 語言系列的標準分隔符號,一個 statement 的結束必須以分號為準,並不參考其他的東西(比如分行),這個原則其實很久就受到多方的挑戰,尤其是 script 語言。
我們常見的 script 語言除可使用分號當分隔符號外,大都也可使用分行當分隔符號(如:bash、DOS 的 bat 等)。基於 script 語言強調「簡易、方便」的處理原則,只要想要切入 script 應用的語言,都會考慮分行作為分隔的原則。
例如 JavaScript,他的語法屬於 C 系列(Java 承繼 C 的語法精神、JavaScript 承繼 Java 的語法精神),但 JavaScript 決定分號並不是唯一的分隔符號。在 JavaScript 中你仍然可以使用分號來結束一個 statement ,但只要在允許的範圍內,分號是可有可無的。
何謂允許的範圍?就是「JavaScript Engine 如果可以分辨出一個獨立的 statement」的狀況下,這種狀況最典型的就是分行,因此你若有分行分開兩個 statement,那個分號就已變成可有可無,沒有存在的必要,這時的分號是可以省略的。
Scala 的思想邏輯也是著重在簡單上,希望讓 Programmer 快速開發程式,因此自然有相同省略分號的思考邏輯。
在 Scala 中,只要可以省略分號的地方,你就可以省略,這就是「分號省略原則」。
當然,你若執意要保留分號,以便與 Java 程式碼看起來比較相像,也是可以,只是分號省略是 Scala 比較推薦的方式。
「什麼是只要可以省略分號的地方?」
大部分的 programmer 在一行只會寫下一個 statement,不同的 statement 寫在不同行是絕大多數人的習慣,所以 statement 與 statement 中間通常都會有分行符號,因此預測一個分行代表該行的 statement 的結束是合理的推論。依照這個推論,分行符號通常隱含著一個分號,所以 Scala 把分行當成可以省略分號的地方。
正常情況,Scala 會在行與行之前,偷偷加上分號,所以該行的 statement 會被結束。但下列情況的分行符號,Scala 不會進行偷偷加上分號的動作
1. 該行的命令尚未結束,比如在一個 infix operator 的 statement 中間,或是呼叫某個 object 的 method,但只寫到點「.」這個符號,此時不會自動補上分號。
2. 下一行的 statement 並不是一個正常 statement 的開頭,此時也不會自動在前一行補上分號。
3. 小括號與中括號內部的分行,也不會自動補上分號。
「除以上三點的情況,在一般分行符號加上分號」,這種動作就稱為分號推論「semicolon inference」。
我們來看以下的例子:
var n1: Int = 10; var n2: Int = 20;
我們可以改寫為
var n1: Int = 10 var n2: Int = 20
有沒有分號,兩者所代表的意義,都一模一樣。
3-1. class 宣告
從此篇開始,我們進入 Scala 每個組成分子的實際介紹,請有興趣的朋友跟著我們的程式做。
這篇要談的就是 class 的宣告。啊?太快?太硬?
之前文章曾經提過,Scala 中所有的東西都是 object,所以 class 是它最本的結構。
在 Java 程式中,所有的東西都要定義在 class 中,Scala 也是同樣的情況,所有的東西都要定義在 class 中。因此我們決定從最基礎的 class 談起。
讓我們先看一下 Java 中 class 的宣告方式
上例宣告一個 class J1
J1 裡面有一個 data field 叫 n1
J1 裡面有一個 method 叫 p1
p1 的 return type 為 void(就是沒有return值)
p1 有一個 int 型態的參數x
Scala 的 class 宣告方式與 Java 宣告在含意上非常像,我們先看例子
S1 裡面有一個 data field 叫 n1,起始值為10
S1 裡面有一個 method 叫 p1
p1 的 return type,為 Unit(Unit後面會討論到)
p1 有一個 Int 型態的參數 x
雖然 Scala 的 class 宣告方式與 Java 不太一樣,但精神卻是一致的。
讓我們一個個來看
1.宣告 class 的方式,在 Scala 中與 Java 一樣都是使用 class 這個 key word.
2.宣告變數的方式有更改, 使用 var 宣告
3.宣告 method 的方式有更改,使用 def 宣告
接下來看繼承的方式
Java 的繼承方式
Scala 的繼承方式
有了宣告 class 與繼承的方式,那麼 implements interface 的部份呢?
interface 的觀念在 Scala 中做了大幅度的修正,觀念也不同了,這部份比較複雜,我們以後的篇幅,再詳論 Java 的 interface 在 Scala 如何修正的。
以下幾篇我們將詳論 Scala 在 class 宣告中各個組成份子。請記得是 Scala 的 class 宣告與繼承與 Java 的方式非常類似,都是使用 class 與 extends,但 interface 的部份,Scala 已經大幅修改。
這篇要談的就是 class 的宣告。啊?太快?太硬?
之前文章曾經提過,Scala 中所有的東西都是 object,所以 class 是它最本的結構。
在 Java 程式中,所有的東西都要定義在 class 中,Scala 也是同樣的情況,所有的東西都要定義在 class 中。因此我們決定從最基礎的 class 談起。
讓我們先看一下 Java 中 class 的宣告方式
class J1 { int n1; void p1(int x) { System.out.println("p1:" + x); } }
上例宣告一個 class J1
J1 裡面有一個 data field 叫 n1
J1 裡面有一個 method 叫 p1
p1 的 return type 為 void(就是沒有return值)
p1 有一個 int 型態的參數x
Scala 的 class 宣告方式與 Java 宣告在含意上非常像,我們先看例子
class S1 { var n1: Int = 10 def p1(x: Int): Unit = { Console.println("p1:" + x) } }上例宣告一個 class S1
S1 裡面有一個 data field 叫 n1,起始值為10
S1 裡面有一個 method 叫 p1
p1 的 return type,為 Unit(Unit後面會討論到)
p1 有一個 Int 型態的參數 x
雖然 Scala 的 class 宣告方式與 Java 不太一樣,但精神卻是一致的。
讓我們一個個來看
1.宣告 class 的方式,在 Scala 中與 Java 一樣都是使用 class 這個 key word.
2.宣告變數的方式有更改, 使用 var 宣告
3.宣告 method 的方式有更改,使用 def 宣告
接下來看繼承的方式
Java 的繼承方式
class J2 extends J1 { void p2() { System.out.println("p2"); } }
Scala 的繼承方式
class S2 extends S2 { def p2(): Unit = { Console.println("p2") } }Scala 繼承方式與 Java 很像,都是使用 extends 這個 key word。
有了宣告 class 與繼承的方式,那麼 implements interface 的部份呢?
interface 的觀念在 Scala 中做了大幅度的修正,觀念也不同了,這部份比較複雜,我們以後的篇幅,再詳論 Java 的 interface 在 Scala 如何修正的。
以下幾篇我們將詳論 Scala 在 class 宣告中各個組成份子。請記得是 Scala 的 class 宣告與繼承與 Java 的方式非常類似,都是使用 class 與 extends,但 interface 的部份,Scala 已經大幅修改。
2-7. Scala 經典學習
Scala 範圍廣大,沒有方向是不易學習的,在 Scala 世界中,有幾個地方你不宜錯過,以下簡單介紹
1. Scala 大本營的說明:位在此http://www.scala-lang.org/node/274,當你使用 Scala 的開發過程有不熟悉的地方,可以參閱此處的相關說明。
2. Programming in Scala:一本好書,Martin Odersky (Scala設計者) 與 Bill Venners (Inside the Java Virtual Machine 作者) 共同撰寫,已經有第二版。

3.Programming Scala:另一本好書,最好的是可以線上閱讀。請參閱 http://programming-scala.labs.oreilly.com/index.html

以上,是你學習 Scala 的好地方,其他的學習就是線上演練,實際寫些程式,試著做。
你若熟悉 Java,慢慢你會發現,Scala 沒有那麼難懂,瞭解它後,你會覺得,其實它還蠻可愛的!
Scala 的介紹到此告一段落,接下來將會實際介紹 Scala 的各個組成分子。
同樣的,我們鎖定你是 Java 的開發者,我們會以 Java 的角度來解釋 Scala 的各個組成分子,請繫緊安全帶,準備出發。
1. Scala 大本營的說明:位在此http://www.scala-lang.org/node/274,當你使用 Scala 的開發過程有不熟悉的地方,可以參閱此處的相關說明。
2. Programming in Scala:一本好書,Martin Odersky (Scala設計者) 與 Bill Venners (Inside the Java Virtual Machine 作者) 共同撰寫,已經有第二版。

3.Programming Scala:另一本好書,最好的是可以線上閱讀。請參閱 http://programming-scala.labs.oreilly.com/index.html

以上,是你學習 Scala 的好地方,其他的學習就是線上演練,實際寫些程式,試著做。
你若熟悉 Java,慢慢你會發現,Scala 沒有那麼難懂,瞭解它後,你會覺得,其實它還蠻可愛的!
Scala 的介紹到此告一段落,接下來將會實際介紹 Scala 的各個組成分子。
同樣的,我們鎖定你是 Java 的開發者,我們會以 Java 的角度來解釋 Scala 的各個組成分子,請繫緊安全帶,準備出發。
2-6. 其它的Scala工具或Library
除了之前介紹的 Lif t 與 Akka, Scala 也有許多好用的 library,Scala 主站也蒐集一些,大家可以參考
1. Contributed Libraries and Tools:http://www.scala-lang.org/node/1209
2.Scala Bazaar(或稱sbaz):http://www.scala-lang.org/node/93
1. Contributed Libraries and Tools:http://www.scala-lang.org/node/1209
2.Scala Bazaar(或稱sbaz):http://www.scala-lang.org/node/93
2-5. 轉移到Scala,有風險嗎?
學習一個新語言,除了該語言的功能與易學性需要考慮以外,對於該語言各種應用的解決方案,以及如何延續自己既有的程式資產,也都應該列入考量的範圍。
我們發現有很多新的語言標榜很多功能,但對於解決方案的支援卻很缺乏,這時使用者是否要轉而接受該語言,就有待考驗。
同樣的情況,也出現在 Scala 上,Scala 就算再強,也不可能解決所有的問題,我們真的可以放心轉移到 Scala 嗎?Web 怎麼辦?Database 怎麼辦?
這些問題在 Scala 世界中,可能不會那個嚴重。原因是因為 Scala 可以繼承 Java 廣大的解決方案。
前面提過 Scala 與 Java 彼此可以混用,只要是 Java 的 library、package 或 framework,Scala 都可以使用,無形中,Scala 已有成堆的解決方案。可以使用 Java 的資產,也是 Scala 設計時重要的考量因素之一。
在同一團隊中,使用 Scala 與 Java 寫作出來的程式碼,因為可以互相混用,因此也少了移轉障礙,這對進入 Scala 世界少了很多的障礙。盡量繼續使用你原有 Java 的資產,不會因為進入Scala 世界而要完全放棄過去的投資,只是你以後要有使用兩種語言寫程式的心理打算,合適 Scala 的時候使用 Scala,合適 Java 的時候使用 Java。
但這是否代表在 Scala 世界中,不提供一些常見的解決方案?
當然不是這樣,在 Scala 世界中也有許多很棒的設計,以下簡單說明:
一.Web 解決方案
Web是現在最主流的開發方式,不管 Windows、Java、PHP、Ruby 都有一大堆人投入其中。Ruby 這個語言本來默默無聞,但藉著 Ruby on Rail 名震天下,有許多所謂 Web 2.0 的網站是用 ROR 所寫作的。ROR 的成功也讓 Java 意識到自己的老舊與繁瑣,而有許多改進聲音出現(如:closure、continuation 都是那時要求改進的項目)。
我們發現有很多新的語言標榜很多功能,但對於解決方案的支援卻很缺乏,這時使用者是否要轉而接受該語言,就有待考驗。
同樣的情況,也出現在 Scala 上,Scala 就算再強,也不可能解決所有的問題,我們真的可以放心轉移到 Scala 嗎?Web 怎麼辦?Database 怎麼辦?
這些問題在 Scala 世界中,可能不會那個嚴重。原因是因為 Scala 可以繼承 Java 廣大的解決方案。
前面提過 Scala 與 Java 彼此可以混用,只要是 Java 的 library、package 或 framework,Scala 都可以使用,無形中,Scala 已有成堆的解決方案。可以使用 Java 的資產,也是 Scala 設計時重要的考量因素之一。
在同一團隊中,使用 Scala 與 Java 寫作出來的程式碼,因為可以互相混用,因此也少了移轉障礙,這對進入 Scala 世界少了很多的障礙。盡量繼續使用你原有 Java 的資產,不會因為進入Scala 世界而要完全放棄過去的投資,只是你以後要有使用兩種語言寫程式的心理打算,合適 Scala 的時候使用 Scala,合適 Java 的時候使用 Java。
但這是否代表在 Scala 世界中,不提供一些常見的解決方案?
當然不是這樣,在 Scala 世界中也有許多很棒的設計,以下簡單說明:
一.Web 解決方案
Web是現在最主流的開發方式,不管 Windows、Java、PHP、Ruby 都有一大堆人投入其中。Ruby 這個語言本來默默無聞,但藉著 Ruby on Rail 名震天下,有許多所謂 Web 2.0 的網站是用 ROR 所寫作的。ROR 的成功也讓 Java 意識到自己的老舊與繁瑣,而有許多改進聲音出現(如:closure、continuation 都是那時要求改進的項目)。
Java 世界中,Web 的解決方案更是多元,有 Servlet、JSP、JSF、各式的 framework(Wicket、Struct、Tapestry、Spring)、各種 template(Velocity、FreeMaker)、Groovy 的 GSP、Grails等。看到這,你應該累了,Java 應該是有史以來產生最多 framework 的語言。
在 Scala 中,有一個非常有名的 Web 解決方案,名叫 Lift,設計者 David 在瞭解 ROR 以及 Wicket 後,所設計出來給 Scala 世界的一個很好的 Web 解決方案,非常有名。
很有趣的是,David 現在想要將這個解決方案,推銷到 Ruby 世界中,希望 Ruby 的使用者可以透過 JRuby 來使用 Lift,可見得設計者對這個產品的信心。
很有趣的是,David 現在想要將這個解決方案,推銷到 Ruby 世界中,希望 Ruby 的使用者可以透過 JRuby 來使用 Lift,可見得設計者對這個產品的信心。
Lift 這個東西很有用,若你希望使用 Scala 撰寫 Web AP,你應該不可忽視它。這麼重要的軟體,未來我們有機會將討論它。
二.平行處理
Scala 對於平行處理著墨甚多,可見得平行處理本身的困難度有多大。
在平行處理的問題上,除 Scala 本身提供的 Actor Model 外,在 Scala 世界中還有一個重量級的解決方案,叫 Akka。
Akka 提供的功能超出 Scala 甚多,包含更精細的 Actor、STM(Software Transaction Memory,把你在 memory 的資料看成和 database 一樣,也有 transaction 的功能) 等,都是解決平行處理問題的關鍵技術。
深受 multi-thread 困擾的朋友,Akka 會是你解決問題的好幫手,這麼重要的東西,未來我們也會討論。對了,Akka 也支援使用 Java 使用(不需透過 Scala),趕快去看看吧。
二.平行處理
Scala 對於平行處理著墨甚多,可見得平行處理本身的困難度有多大。
在平行處理的問題上,除 Scala 本身提供的 Actor Model 外,在 Scala 世界中還有一個重量級的解決方案,叫 Akka。
Akka 提供的功能超出 Scala 甚多,包含更精細的 Actor、STM(Software Transaction Memory,把你在 memory 的資料看成和 database 一樣,也有 transaction 的功能) 等,都是解決平行處理問題的關鍵技術。
深受 multi-thread 困擾的朋友,Akka 會是你解決問題的好幫手,這麼重要的東西,未來我們也會討論。對了,Akka 也支援使用 Java 使用(不需透過 Scala),趕快去看看吧。
2011年4月22日 星期五
2-4. Scala其他工具 --scalap與scaladoc
還有兩個重要 Scala 工具,在你開發 Scala 程式時有很大的幫助,那就是 scalap 與 scaladoc。
看到這個兩個名稱,熟 Java 的朋友應該很容易對應到 Java 的工具,沒錯,這兩個工具就是對應 Java 世界中的 javap 與 javadoc。
javadoc 大部分的朋友比較熟悉,這裡不說明。但對於 javap 或許有比較多的人比較不曉得,值得介紹給大家認識。
javap 可以將 javac compile 後的 classfile 反組譯回來,讓你知道該 classfile 所包含的資訊,你可使用 javap 看到 class 包含哪些欄位、method、甚至可以看到程式碼 (JVM instruction),對於瞭解 Java 執行的流程,有相當多的幫助。以下用例子說明
1.撰寫 java source code並compile
2.使用 javap 查看 J1 所編譯出來的結果
若是你瞭解JVM instruction,可加-c (disassembly)的 optin,展開 method 中的 JVM instruction。JVM instruction 是 JVM 中的 assembly language。
3.使用javap來反組譯classfile
你看到什麼了?很棒吧,所有的程式碼都 show 給你看,你也可以從 javap 看到 javac 幫你產生哪些 method。
這個例子中 J1 並沒有宣告 constructor,但 javac 幫你產生 default constructor,名稱就叫 J1()。
你若喜歡,也可以使用 javap 來幫你查看 scalac 所 compile 出來的 classfile,讓我們現在就來試試。
4.使用 javap 來反組譯 scalac 所產生的 classfile
看到了吧,我們使用 javap 將 Scala 所產生的 classfile 一五一十顯示出來,很方便。
讓我們回到 Scala 的工具。 Scala 中的 scalap 的目的與 javap 類似,也是讓我們可以觀看compile後所產生的classfile,現在讓我們看看執行 scalap 會顯示什麼?
注意:在執行 scalap 之前,你需要將 scalap.jar 放到 classpath 中,否則會產生問題
5.使用 scalap 觀看 scalac 所產生的 classfile
scalap 顯示 class中的 field 與 method,可供你大致瞭解該 classfile 是如何。
scalap 並不重複 javap 所作的工作,但它會嘗試把該 classfile 當成 scalac 所產生來解譯,雖然該classfile 是由 javac 所產生。
讓我們現在來試試看。
6.使用 scalap 觀看 javac 所產生的 classfile
看到了,但好像有問題,J1竟然由 scala.AnyRef 繼承下來?有錯吧?!
其實,scalap 並沒有錯誤,在這裡反而我們可以察覺 Scala 的作用方式。AnyRef(現在不知道沒關係)其實直接對應到 Java 的 Object,
說清楚一點,Scala 中的 AnyRef 在內部運作時直接使用 Java 的 Object。嗯嗯,還是不懂,先不管 AnyRef 了,後面我們會討論到的。
這篇的說明讓我們了解到可以使用 javap、scalap 觀察 scalac 所產生的 classfile,二者都是很重要的工具,對於瞭解 Scala 如何與 Java 攜手合作是非常好的觀察工具,建議大家要好好善用這兩個工具。
看到這個兩個名稱,熟 Java 的朋友應該很容易對應到 Java 的工具,沒錯,這兩個工具就是對應 Java 世界中的 javap 與 javadoc。
javadoc 大部分的朋友比較熟悉,這裡不說明。但對於 javap 或許有比較多的人比較不曉得,值得介紹給大家認識。
javap 可以將 javac compile 後的 classfile 反組譯回來,讓你知道該 classfile 所包含的資訊,你可使用 javap 看到 class 包含哪些欄位、method、甚至可以看到程式碼 (JVM instruction),對於瞭解 Java 執行的流程,有相當多的幫助。以下用例子說明
1.撰寫 java source code並compile
2.使用 javap 查看 J1 所編譯出來的結果
若是你瞭解JVM instruction,可加-c (disassembly)的 optin,展開 method 中的 JVM instruction。JVM instruction 是 JVM 中的 assembly language。
3.使用javap來反組譯classfile
你看到什麼了?很棒吧,所有的程式碼都 show 給你看,你也可以從 javap 看到 javac 幫你產生哪些 method。
這個例子中 J1 並沒有宣告 constructor,但 javac 幫你產生 default constructor,名稱就叫 J1()。
你若喜歡,也可以使用 javap 來幫你查看 scalac 所 compile 出來的 classfile,讓我們現在就來試試。
4.使用 javap 來反組譯 scalac 所產生的 classfile
看到了吧,我們使用 javap 將 Scala 所產生的 classfile 一五一十顯示出來,很方便。
讓我們回到 Scala 的工具。 Scala 中的 scalap 的目的與 javap 類似,也是讓我們可以觀看compile後所產生的classfile,現在讓我們看看執行 scalap 會顯示什麼?
注意:在執行 scalap 之前,你需要將 scalap.jar 放到 classpath 中,否則會產生問題
5.使用 scalap 觀看 scalac 所產生的 classfile
scalap 顯示 class中的 field 與 method,可供你大致瞭解該 classfile 是如何。
scalap 並不重複 javap 所作的工作,但它會嘗試把該 classfile 當成 scalac 所產生來解譯,雖然該classfile 是由 javac 所產生。
讓我們現在來試試看。
6.使用 scalap 觀看 javac 所產生的 classfile
看到了,但好像有問題,J1竟然由 scala.AnyRef 繼承下來?有錯吧?!
其實,scalap 並沒有錯誤,在這裡反而我們可以察覺 Scala 的作用方式。AnyRef(現在不知道沒關係)其實直接對應到 Java 的 Object,
說清楚一點,Scala 中的 AnyRef 在內部運作時直接使用 Java 的 Object。嗯嗯,還是不懂,先不管 AnyRef 了,後面我們會討論到的。
這篇的說明讓我們了解到可以使用 javap、scalap 觀察 scalac 所產生的 classfile,二者都是很重要的工具,對於瞭解 Scala 如何與 Java 攜手合作是非常好的觀察工具,建議大家要好好善用這兩個工具。
2-3. Scala工具 --IDE 與 project building 工具
有人開發Java程式,沒有使用 IDE 工具,就覺得彆扭,若你是這樣的人,Scala 也有幫你想到, IDE 的開發環境在 Scala 也看得到。
但本系列主要以 Scala 語言學習為主,除了基礎的 scalac 與 scala 兩個工具外,並不想深入介紹其他 Scala 的開發工具,原因是這些開發工具與學會 Scala 並不相關。這些工具是輔助或加速開發 Scala 的開發工作,若你學會 Scala 後想要加速開發工作,請自行研究。
現在的 Java IDE 兩大主流為 eclipse 與 netbeans,當然還有其他廠商在開發 Java IDE,
比如 JBuilder、IntelliJ IDEA、Oracle JDeveloper、BlueJ 等,但影響就不如前面兩者大。
在上述 IDE 中,eclipse、netbeans、IntelliJ IDEA 都有支援 Scala,喜歡的人可以自行安裝試試看。
除 IDE 外,使用 Java 開發專案時,你可也會使用 project building 的工具,比如 Apache 的 ant 以及 Apache 的 maven(兩者都是Apache出品,品質有保證!)。
在 Scala 也有類似的東西,叫做 sbt(Simple Build Toole),可以用來進行 project building。有興趣的朋友自行學習,這裡不多加介紹。
2-2. Scala工具 --Interpreter(直譯環境)
在之前文章提過,Scala 支援 interpreter(直譯環境)以及 script 的用法,現在說明。
1. Interpreter(直譯環境)
scala 命令也是 interpreter(直譯環境),當你在 scala 命令後面沒有放置 class_name,會進入直譯環境。
直譯環境執行後,在你的 console 會產生 prompt,通知你輸入命令,你輸入命令後,scala interpreter 會依序執行,並將對應的結果輸出到 console 中。直譯環境是學習 Scala 很好的方式,大家可多瞭解。關於直譯環境的命令,這裡不詳加說明,請自行參閱網站。
2.以 script 的執行方式
Scala 可以直接執行 Scala 所寫成的 script file,該 script file 副檔名可以任意,但最好是 .scala。執行方式仍然使用 scala 命令。
執行方式:scala x1.scala
以上,簡單介紹直譯環境與 script-like 的執行方式。由這些支援,就可瞭解 Scala 在模擬一般的 script language 花下多少心思。
1. Interpreter(直譯環境)
scala 命令也是 interpreter(直譯環境),當你在 scala 命令後面沒有放置 class_name,會進入直譯環境。
直譯環境執行後,在你的 console 會產生 prompt,通知你輸入命令,你輸入命令後,scala interpreter 會依序執行,並將對應的結果輸出到 console 中。直譯環境是學習 Scala 很好的方式,大家可多瞭解。關於直譯環境的命令,這裡不詳加說明,請自行參閱網站。
2.以 script 的執行方式
Scala 可以直接執行 Scala 所寫成的 script file,該 script file 副檔名可以任意,但最好是 .scala。執行方式仍然使用 scala 命令。
執行方式:scala x1.scala
以上,簡單介紹直譯環境與 script-like 的執行方式。由這些支援,就可瞭解 Scala 在模擬一般的 script language 花下多少心思。
2-1. Scala工具 --原始碼的編譯與執行
要學習 Scala 需要先將 Scala 的環境準備好。
這一篇我們將介紹 Scala 的開發工具,但不會詳細介紹 Scala 的各種工具。
本系列的主要目的,是讓大家瞭解 Scala ,可以順利執行 Scala,對於較進階的工具,請各位具備 Scala 基礎知識之後,再自行接觸。
開發 Java 程式,你需要的是 JDK,就是 javac 與 java 兩隻程式。你當然也可使用 IDE 環境來開發 Java 程式,或是使用 Ant、Maven 等工具來編譯你的 Java 程式碼,但這些進階的工具並不是開發 Java 程式所必備。
同樣,在 Scala 世界,我們也只需基本工具就可開發 Scala 程式,我們不擬討論 Scala 中進階的工具,但我們會告訴你到何處取得這些資訊。
Scala 的開發與 Java 相類似,一個editor,一個compiler,一個executor,就可以了,很簡單。
editor 你自行準備,compiler 與 executor 這邊會告訴你。
Scala 的基礎工具可以到 Scala 的大本營 (http://www.scala-lang.org/) 去 download,裡面會包含 compiler 與 executor,還有其他的東西。
在進行之前,請記得 Scala 所編譯出來的就是 Java 的 Bytecode(Scala 也可編譯出 .Net 的程式碼,但 .Net 本系列不擬討論,有興趣者自行到 Scala 大本營查詢)。
Scala 的執行與 Java 的執行一樣,都由 JVM 啟動,所以執行 Scala 程式,會依循 JVM 的原則,在執行階段做 linkage(所謂的 linkage 就是找到正確的 class files),所以請記得設定好你的classpath。
要順利執行 Scala,首先需要 JDK,關於 JDK 的取得與安裝,你應該會知道,其他的步驟如下:
一. Download Scala package、解壓縮、設定PATH
四.執行
五.第二種執行方式
2.加上 scala-library.jar,再執行一次,這次就OK了。
要準備的開發環境就是這麼簡單,與 Java 的大同小異,你若熟悉 Java,應該不會有問題。
這一篇我們將介紹 Scala 的開發工具,但不會詳細介紹 Scala 的各種工具。
本系列的主要目的,是讓大家瞭解 Scala ,可以順利執行 Scala,對於較進階的工具,請各位具備 Scala 基礎知識之後,再自行接觸。
開發 Java 程式,你需要的是 JDK,就是 javac 與 java 兩隻程式。你當然也可使用 IDE 環境來開發 Java 程式,或是使用 Ant、Maven 等工具來編譯你的 Java 程式碼,但這些進階的工具並不是開發 Java 程式所必備。
同樣,在 Scala 世界,我們也只需基本工具就可開發 Scala 程式,我們不擬討論 Scala 中進階的工具,但我們會告訴你到何處取得這些資訊。
Scala 的開發與 Java 相類似,一個editor,一個compiler,一個executor,就可以了,很簡單。
editor 你自行準備,compiler 與 executor 這邊會告訴你。
Scala 的基礎工具可以到 Scala 的大本營 (http://www.scala-lang.org/) 去 download,裡面會包含 compiler 與 executor,還有其他的東西。
在進行之前,請記得 Scala 所編譯出來的就是 Java 的 Bytecode(Scala 也可編譯出 .Net 的程式碼,但 .Net 本系列不擬討論,有興趣者自行到 Scala 大本營查詢)。
Scala 的執行與 Java 的執行一樣,都由 JVM 啟動,所以執行 Scala 程式,會依循 JVM 的原則,在執行階段做 linkage(所謂的 linkage 就是找到正確的 class files),所以請記得設定好你的classpath。
要順利執行 Scala,首先需要 JDK,關於 JDK 的取得與安裝,你應該會知道,其他的步驟如下:
一. Download Scala package、解壓縮、設定PATH
- Download 回來的 scala,把它解壓縮到一個目錄,記得將該目錄的bin子目錄加到你的PATH中。
- 例如:你將 download 回來的 scala 解壓縮到 c:\scala\ 目錄底下,此時你需要將 c:\scala\bin 放到 PATH 中。
- 將 c:\scala\lib 加到你的 classpath 中。
- 此步驟是當你想要使用 java 執行檔直接執行你寫的 Scala 程式時。
- 當你程式撰寫完成,需使用 Scala 的 compiler 編譯你的程式碼。Scala 編譯出來的程式碼是 Java bytecode(也有 .Net 環境的 CLR碼,本系列不討論)。Scala 的 compiler 有兩個,一個稱為 scalac,另一個稱為 fsc,二者功用完全相同。
- 第一次使用 fsc(fast scala compiler)時,會啟動 compilation daemon,常駐在記憶體中,下次再使用 fsc 時,就會直接使用該 daemon,加快 compile 速度。
- 使用 fsc 或是 scalac 來 compile 你的Scala程式碼,fsc/scalac 與 javac 的用法類似,會將 Scala 編譯出來的 bytecode 放到你指定的目錄中。關於 fsc/scalac 的詳細命令請自行參考命令的用法。
四.執行
- 當 compile 完畢後,就可以使用 scala class_name 來執行。
- 與 Java 相同,compile 後 bytecode 放置的位置需要設定到 classpath 中,否則會有 class not found 的 exception 產生。
五.第二種執行方式
- Scala 所編譯出來的 bytecode 與 Java 所編譯出來 bytecode 並沒有分別,可以直接使用 java 這個命令來執行 Scala 所編譯出來的 class。
- 使用 JVM 直接啟動 Scala所產生的 bytecode,需要將 Scala 所附的library(該 library 名稱為scala-library.jar,該 .jar 檔在你 scala 目錄中的 lib 子目錄可找得到)加到你的 classpath,然後依照一般 Java 程式啟動的方法即可啟動。
2.加上 scala-library.jar,再執行一次,這次就OK了。
要準備的開發環境就是這麼簡單,與 Java 的大同小異,你若熟悉 Java,應該不會有問題。
2011年4月20日 星期三
1-4. Scala太複雜?學不會!
前面提到 Scala 的特性,現在看不懂其實沒有關係。相信我,若你是 Java 的 Programmer,學會 Scala 後,你一定會喜歡它,對你開發工作必定有大幅幫助。
「Scala有這麼多的特色,這麼複雜,怎麼辦,學不會啦!」
針對這個問題,國外有人提出解答「沒完全學會沒關係,先學你需要用到的地方就好了」。
本來,Scala 包山包海,不可能一次學得完全、學得精。如果你只是要一個更好的script語言,學習 script 會用到的地方就好了。
本來,Scala 包山包海,不可能一次學得完全、學得精。如果你只是要一個更好的script語言,學習 script 會用到的地方就好了。
上面那段話的意思是說,用 Scala 撰寫程式沒完全學會沒關係,不一定要把 Scala 全部特性都使用在你的程式中。
邊寫邊學習,在尚未熟習 Scala 的各種功能之前,可以把 Scala 當成不同語法的 Java 來看待,只使用知道的 Scala 功能來撰寫程式。
當學習完成,各種 Scala 的特性你也熟練後,就可依程式的特性,使用 Scala 不同的特性來設計程式,此時你使用 Scala 起來,將得心應手,就會大幅降低你程式開發的時間。
邊寫邊學習,在尚未熟習 Scala 的各種功能之前,可以把 Scala 當成不同語法的 Java 來看待,只使用知道的 Scala 功能來撰寫程式。
當學習完成,各種 Scala 的特性你也熟練後,就可依程式的特性,使用 Scala 不同的特性來設計程式,此時你使用 Scala 起來,將得心應手,就會大幅降低你程式開發的時間。
「邊寫邊學習?怎麼聽起來好像怪怪的,有落空不踏實的感覺,這只是安慰人嗎?」
「可是我會怕耶,會不會老闆看到我 Scala 程式,沒有好好運用 Scala 好的功能,察覺到我不用功?」
關於這個顧慮,國外倒是沒有人回答。
也許,更好的解釋是, 依照 Scala 的複雜度,連你老板也不知道更好的寫作方式,所以,放心啦!
這樣說,你會釋懷嗎?
不管如何,多瞭解一個強而有力的與語言,終究不會是壞事。
我們即將進入 Scala 的世界,在台灣,會 Java 的 Programmer 相當多,Scala 承繼自 Java,因此我們會以 Java Programmer 的角度來帶領各位學習 Scala。
對於那些不熟 Java 的讀者或許會有點吃力,尚請見諒。
關於這個顧慮,國外倒是沒有人回答。
也許,更好的解釋是, 依照 Scala 的複雜度,連你老板也不知道更好的寫作方式,所以,放心啦!
這樣說,你會釋懷嗎?
不管如何,多瞭解一個強而有力的與語言,終究不會是壞事。
我們即將進入 Scala 的世界,在台灣,會 Java 的 Programmer 相當多,Scala 承繼自 Java,因此我們會以 Java Programmer 的角度來帶領各位學習 Scala。
對於那些不熟 Java 的讀者或許會有點吃力,尚請見諒。
1-3. Scala的特性
Scala 包含許許多多的特性,這些特性來自於 Scala 的目的。Scala 的目的是想要解決很多很多的事,最好把所有關於程式設計相關的事,全部使用同一種程式語言來解決。
Scala 具有各種不同的面貌:
1.整合命令式(Imperative)與函數式(Functional)兩種語言模式。
2.使用強制型態,但維持大部分的動態型態的方便性:使用型態推論(Type Inference),允許在 Compiler 可自動推論的情況下,不需宣告變數的特性。
3.Scala主要是 Compiler 的運作模式,但它也可當成 interpreter 來使用。
4.Scala可以當成 script 語言,也具有一個直譯環境,讓你直接敲入 Scala 程式碼,馬上執行,就像久遠以前的 Basic 直譯環境。
5.Scala是一個純 OO的語言,每個東西都是 object,但為兼顧primitive data的效能優點,compiler會針對 Int / Float 等數值資料,compile 出來的 bytecode使用 primitive type。
6.Scala的效能與 Java 的效能相當,使用 Scala 撰寫程式並不會損壞效能。
7.Scala與Java可以完全混用。
8.Scala可以編譯出 JVM 的 bytecode,也可以編譯出.Net的程式碼。
9.Scala充分支援generic(泛型),並且導入更廣泛的type system。
10.Scala相當注重concurrency開發,除導入有名 Actor Model 外,並大量要求 programmer 盡量使用 concurrency 安全的寫作方式。
11.Scala在語言中直接支援 XML,讓XML的處理顯得更方便。
12.Scala的Pattern Match是很強大的功能,可以大幅簡化比較的工作。
13.DSL:使用Scala可以快速建立領域相關的語言(Domain Specific Language)。
以上,這些特性造成 Scala功能強大的原因,但也造成 Scala 學習起來比較艱難的原因。
關於Scala的設計目的請參閱 「Scala的企圖心與挑戰」,那裡有比較詳細的說明。
Scala 具有各種不同的面貌:
1.整合命令式(Imperative)與函數式(Functional)兩種語言模式。
2.使用強制型態,但維持大部分的動態型態的方便性:使用型態推論(Type Inference),允許在 Compiler 可自動推論的情況下,不需宣告變數的特性。
3.Scala主要是 Compiler 的運作模式,但它也可當成 interpreter 來使用。
4.Scala可以當成 script 語言,也具有一個直譯環境,讓你直接敲入 Scala 程式碼,馬上執行,就像久遠以前的 Basic 直譯環境。
5.Scala是一個純 OO的語言,每個東西都是 object,但為兼顧primitive data的效能優點,compiler會針對 Int / Float 等數值資料,compile 出來的 bytecode使用 primitive type。
6.Scala的效能與 Java 的效能相當,使用 Scala 撰寫程式並不會損壞效能。
7.Scala與Java可以完全混用。
8.Scala可以編譯出 JVM 的 bytecode,也可以編譯出.Net的程式碼。
9.Scala充分支援generic(泛型),並且導入更廣泛的type system。
10.Scala相當注重concurrency開發,除導入有名 Actor Model 外,並大量要求 programmer 盡量使用 concurrency 安全的寫作方式。
11.Scala在語言中直接支援 XML,讓XML的處理顯得更方便。
12.Scala的Pattern Match是很強大的功能,可以大幅簡化比較的工作。
13.DSL:使用Scala可以快速建立領域相關的語言(Domain Specific Language)。
以上,這些特性造成 Scala功能強大的原因,但也造成 Scala 學習起來比較艱難的原因。
關於Scala的設計目的請參閱 「Scala的企圖心與挑戰」,那裡有比較詳細的說明。
1-2. Scala 的歷史
Scala 的設計者是 Martin Odersky,以下是他的一些簡史
Scala 版本
名人的加持
- 在 Java 尚未支援泛型(generic)時,Martin 曾經設計過 Pizza Language、Generic Java(GJ),這兩個語言都是在 Java 中支援泛型(generic)的概念,Java 最終將泛型納入語言中。
- Martin Odersky 曾在 javac (Java Compiler)團隊工作,對於 compiler 技術相當熟悉。
- 2001年開始,Martin 在 École Polytechnique Fédérale de Lausanne (EPFL) 設計 Scala,在使用 Scala 的過程中,我們有時可看到 EPFL 的字眼。
Scala 版本
- 2003年底 Scala 釋出在 JVM 中的版本。
- 2004年釋出在 .Net上版本。
- 以後持續演進中...。
名人的加持
- Java 的設計者 James Gosling 曾提過,除了 Java 外,若讓他挑選一個程式語言,他的挑選目標會是 Scala。「 If I were to pick a language to use today other than Java, it would be Scala. 」
- Groovy的設計者 James Strachan 曾提過,若有人將 Scala 告訴他,他很可能就不嘗試設計 Groovy。「I can honestly say if someone had shown me the Programming in Scala book by by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy. 」
1-1. Scala新接觸
Scala是一個承繼Java的程式語言
Java開發的繁複性,是眾所周知,也是大家很頭痛的,因此有許許多多的方案要來解決這個問題,JRuby、Groovy、AspectJ都努力過,然而好像沒成功。
Scala重新設計程式語言的組成分子,讓他在開發上更快速、更容易寫出正確的程式、又不失執行時期的效能,讓這個語言脫穎而出,慢慢吸引程式設計者的眼光,未來也許有機會成為在JVM與Java相輔相成的語言(雖然Scala不只可以在JVM運作)。
對於它的好,已有許多地方為它宣傳,這裡不多贅言。
雖然它好用,雖然它強,但對於新接觸者,它卻透露出嚴重的缺點,就是複雜,難以學習。
回想Java剛升起的時代,那時C是主要的開發語言,C++是最主要的Object-Oriented語言,在C系列盤據的地盤中,Java脫穎而出,有相關的時空背景,但C++的複雜性與Java的簡單也是造成程式者轉向Java的原因之一。
關於C++的複雜,這裡不贅言,有經驗的C++程式者,想想看光一個method宣告,其中const放在不同的地方就有不同的效果,就讓人生氣,也知道C++是如何要求程式開發者的智力與謹慎程度。
Scala,有人形容它就像C++一樣,這麼的難以親近,那它有機會成功嗎?
個人覺得Scala的複雜是來自於它的企圖心與設計理念,Scala的企圖心由他的命名Scalable Language,就可以印證。
想瞭解 Scala 的設計理念,請參考「Scala的企圖心與挑戰」。本系列將繼續探討如何使用 Scala。
Java開發的繁複性,是眾所周知,也是大家很頭痛的,因此有許許多多的方案要來解決這個問題,JRuby、Groovy、AspectJ都努力過,然而好像沒成功。
Scala重新設計程式語言的組成分子,讓他在開發上更快速、更容易寫出正確的程式、又不失執行時期的效能,讓這個語言脫穎而出,慢慢吸引程式設計者的眼光,未來也許有機會成為在JVM與Java相輔相成的語言(雖然Scala不只可以在JVM運作)。
對於它的好,已有許多地方為它宣傳,這裡不多贅言。
雖然它好用,雖然它強,但對於新接觸者,它卻透露出嚴重的缺點,就是複雜,難以學習。
回想Java剛升起的時代,那時C是主要的開發語言,C++是最主要的Object-Oriented語言,在C系列盤據的地盤中,Java脫穎而出,有相關的時空背景,但C++的複雜性與Java的簡單也是造成程式者轉向Java的原因之一。
關於C++的複雜,這裡不贅言,有經驗的C++程式者,想想看光一個method宣告,其中const放在不同的地方就有不同的效果,就讓人生氣,也知道C++是如何要求程式開發者的智力與謹慎程度。
Scala,有人形容它就像C++一樣,這麼的難以親近,那它有機會成功嗎?
個人覺得Scala的複雜是來自於它的企圖心與設計理念,Scala的企圖心由他的命名Scalable Language,就可以印證。
想瞭解 Scala 的設計理念,請參考「Scala的企圖心與挑戰」。本系列將繼續探討如何使用 Scala。
釋迦,思家
釋迦:能與勇之族
佳樂之水:台灣景點,好玩
思家:晚上幾點了...程式設計者,思家啊!
盼有個好用的程式語言,來幫助程式設計者
Scala,一個新穎的程式語言
Scala,一個強而有力的程式語言
Scala,也是一個複雜的程式語言
在這裡,分享Scala
這一系例的文章,希望讓來到的朋友,瞭解它,駕馭它,最後喜愛它
若您是一個Java的開發者,這麼適合您的程式語言,您實在應該好好瞭解它
James Gosling, creator of Java
" If I were to pick a language to use today other than Java, it would be Scala. "
James Strachan, creator of Groovy
"I can honestly say if someone had shown me the Programming in Scala book by by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy. "
釋迦:有能有識者
釋迦:台東名產,好吃佳樂之水:台灣景點,好玩
思家:晚上幾點了...程式設計者,思家啊!
盼有個好用的程式語言,來幫助程式設計者
Scala,一個新穎的程式語言
Scala,一個強而有力的程式語言
Scala,也是一個複雜的程式語言
在這裡,分享Scala
這一系例的文章,希望讓來到的朋友,瞭解它,駕馭它,最後喜愛它
若您是一個Java的開發者,這麼適合您的程式語言,您實在應該好好瞭解它
James Gosling, creator of Java
" If I were to pick a language to use today other than Java, it would be Scala. "
James Strachan, creator of Groovy
"I can honestly say if someone had shown me the Programming in Scala book by by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy. "
訂閱:
文章 (Atom)