前言 :
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. Scala 本身具有擴充性,不過這必須了解更多語法特性與細節.
以名呼叫參數(By-name parameter):
到目前為止,所定義函式若有參數,則呼叫時必須先運算出引數值方可呼叫函式。例如 :
在呼叫 sum 函式之前,1+2 與 3+4 都會先運算出結果,然後以 sum(3, 7) 來呼叫函式,a 與 b 參數稱之為以值呼叫參數(By-value paramenter). 來考慮一種情況,你想開發一個函式如下 :
- ByNameParam1.scala 代碼 :
這個函式的作用是,除非 cond 條件成立(也就是 true),否則就執行所傳入的函式物件(也就是 if 的相反). 所傳入的函式物件,並沒有定義參數,不過 () => 仍不能省略,也就是你不可以寫成 :
- unless(false, println("XD"))
在上例中,expr 的型態是=>Any,稱之為以名呼叫參數(By-name parameter),注意到在呼叫 unless 函式時,直接寫下了 println("XD") 這樣的運算式,省略了()=> 的撰寫。事實上,省略 ()=>並不是這個範例的重點,重點是在於println("XD")不會被馬上執行,真正的執行是在 cond 為false,也就是 unless 中 if 結果為true時. 以名呼叫參數正如其名,給予所指定的運算式一個名稱,以這個名稱代替運算式的執行結果來呼叫函式,真正的運算式執行,則是在你所定義的函式之中. 注意!以名呼叫參數並不是函式物件,它是運算式的代表名稱,所以你不可以這麼寫 :
- def unless(cond: Boolean, expr: => Any) = {
- if(!cond) {
- expr() // 不能有括號
- }
- }
以下這個範例可以證明上面的 and 函式確實有捷徑運算的作用 :
由於第一個 and 函式呼叫時,5>3 成立,所以必須測試第二個運算式,因而會顯示 run... 訊息,而第二個 and 函式呼叫時,由於 1>3 為 false,不用再測試第二個運算式,直接傳回 false,所以不會顯示 run... 訊息. 在 Scala 中,沒有 until 的功能,也就是除非條件式成立,否則不斷執行迴圈的功能,以下是個模擬 until 功能的函式 :
如果將第一個參數改為 cond: Boolean=true,until 將永遠不會停止,因為 count == 0 會先運算為 false 再用以呼叫 until 函式,所以 until 中 !cond 將永遠為 true,所以會一直遞迴呼叫下去,直到遞迴堆疊溢值為止. 事實上,如果搭配 Scala 中 鞣製(Curry) 的特性,可以讓這邊的 unless 與 until 看起來就像是語言內建的語法,這也是 Scala 支援擴充性的一個方式.
Supplement
* Tutorialspoint - Scala Data Types
沒有留言:
張貼留言