程式扎記: [Scala 小學堂] Scala Gossic : 了解更多 - 定義函式 (部份套用函式)

標籤

2016年5月23日 星期一

[Scala 小學堂] Scala Gossic : 了解更多 - 定義函式 (部份套用函式)

轉載自 這裡 
前言 : 
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. Scala 本身具有擴充性,不過這必須了解更多語法特性與細節. 

部份套用函式(Partially applied function) : 
所謂的部份套用,是指對某個已定義的函式,希望先對某些參數套用指定的值,之後需要時再指定剩下未定參數的值, 例如 : 
- PartiallyAppFun1.scala 代碼 :
  1. import scala.Math._  
  2.   
  3. def sumOfCubes(a: Double, b: Double, c: Double) = pow(a, 3) + pow(b, 3) + pow(c, 3)  
  4.   
  5. val sumOfCubes32 = sumOfCubes(32, _:Double)  
  6. println(sumOfCubes32(4))  //Show 99  

原先的 sumOfCubes 函式定義了三個參數,現在假設你希望其中兩個參數預定為 3、2,方便接下來的程式只需呼叫一個參數的版本,則可以使用範例中的方 式,先套用部份參數,而未套用的部份使用佔位字元與型態宣告保留下來,這樣的語法會傳回一個函式物件,型態為(Double) => Double,你將之指定給 sumOfCubes32 參考,之後就可以只指定未套用參數的值. 部份套用函式的語法會傳回函式物件,實際上所產生的函式 物件其類別來源,是由編譯器自動產生,這個自動產生的類別,會有個 apply 方法,正如 Scala 語法的一致性,如果要呼叫某個 apply 方法,可以只使 用括號,所以 sumOfCubes32(4),其實是轉為呼叫 sumOfCubes32.apply(4)。以下是另一個範例,用以證明方才的說法 : 
- PartiallyAppFun2.scala 代碼 :
  1. import scala.Math._  
  2.   
  3. def sumOfCubes(a: Double, b: Double, c: Double)=pow(a, 3)+pow(b, 3)+pow(c, 3)  
  4.   
  5. val sumOfCubes3 = sumOfCubes(3, _: Double, _: Double)  
  6. println(sumOfCubes3(45))        // Show 216  
  7. println(sumOfCubes3.apply(45))  // Show 216  

如果你想要 : 
  1. val s = sumOfCubes(_: Double , _: Double, _: Double)  
則可以簡寫為 : 
  1. val s = sumOfCubes _  
_ 可以看作是,代表 sumOfCubes 整個參數列這個語法的作用之一,就是能將 def 所定義的函式轉換為函式物件來傳遞,相當於你這麼定義 : 
  1. import scala.Math._  
  2. val sumOfCubes=(a: Double, b: Double, c: Double) => pow(a, 3)+pow(b, 3)+pow(c, 3)  
例如在使用陣列的 foreach 方法時,你可以這麼使用 : 
  1. Array(123).foreach(x => println(x))  
你也可以使用佔位字元語法來簡化 : 
  1. Array(123).foreach(println(_))  
若使用部份套用函式語法的話,則可以這麼撰寫 : 
  1. Array(123).foreach(println _)   // 相當於 .foreach(x => println(x))  
注意!上面這個不是佔位字元語法,而是部份套用函式的語法,如果用_代表整個參數列,並將函式物件傳給另一個函式作為引數時,可以省略_不寫,也就是寫為 : 
  1. Array(123).foreach(println)  
注意!只寫下函式名稱的方式,僅在將函式物件傳遞給另一個函式作為引數時可以使用,為部份套用語法的簡寫方式,如果你試圖 : 
import scala.Math._
def sumOfCubes(a: Double, b: Double, c: Double)=pow(a, 3)+pow(b, 3)+pow(c, 3)
val s = sumOfCubes
 // 這是錯的

則會出現以下的錯誤訊息 : 

沒有留言:

張貼留言

網誌存檔

關於我自己

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