部份套用函式(Partially applied function)


部份套用函式(Partially applied function)所謂的部份套用,是指對某個已定義的函式,希望先對某些參數套用指定的值,之後需要時再指定剩下未定參數的值。

例如:
import scala.Math._

def sumOfCubes(a: Double, b: Double, c: Double)=pow(a, 3)+pow(b, 3)+pow(c, 3)

val sumOfCubes32 = sumOfCubes(3, 2, _: Double)
println(sumOfCubes32(4)) // 顯示 99.0

原 先的sumOfCubes函式定義了三個參數,現在假設你希望其中兩個參數預定為3、2,方便接下來的程式只需呼叫一個參數的版本,則可以使用範例中的方 式,先套用部份參數,而未套用的部份使用佔位字元與型態宣告保留下來,這樣的語法會傳回一個函式物件,型態為(Double) => Double,你將之指定給sumOfCubes32參考,之後就可以只指定未套用參數的值。

部份套用函式的語法會傳回函式物件,實際上所產生的函式 物件其類別來源,是由編譯器自動產生,這個自動產生的類別,會有個apply方法,正如Scala語法的一致性,如果要呼叫某個apply方法,可以只使 用括號,所以sumOfCubes32(4),其實是轉為呼叫sumOfCubes32.apply(4)。以下是另一個範例,用以證明方才的說法:
import scala.Math._

def sumOfCubes(a: Double, b: Double, c: Double)=pow(a, 3)+pow(b, 3)+pow(c, 3)

val sumOfCubes3 = sumOfCubes(3, _: Double, _: Double)
println(sumOfCubes3(4, 5)) // 顯示 216.0
println(sumOfCubes3.apply(4, 5)) // 顯示 216.0

如果你想要:
val s = sumOfCubes(_: Double , _: Double, _: Double)

則可以簡寫為:
val s = sumOfCubes _

_可以看作是,代表sumOfCubes整個參數列。這個語法的作用之一,就是能將def所定義的函式轉換為函式物件來傳遞,相當於你這麼定義:
import scala.Math._
val sumOfCubes=(a: Double, b: Double, c: Double) => pow(a, 3)+pow(b, 3)+pow(c, 3)


例如在使用陣列的foreach方法時,你可以這麼使用:
Array(1, 2, 3).foreach(x => println(x))

你也可以使用佔位字元語法來簡化:
Array(1, 2, 3).foreach(println(_))

若使用部份套用函式語法的話,則可以這麼撰寫:
Array(1, 2, 3).foreach(println _)   // 相當於 .foreach(x => println(x))

注意!上面這個不是佔位字元語法,而是部份套用函式的語法,如果用_代表整個參數列,並將函式物件傳給另一個函式作為引數時,可以省略_不寫,也就是寫為:
Array(1, 2, 3).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       // 這是錯的

則會出現以下的錯誤訊息:
error: missing arguments for method sumOfCubes; follow this method with `_' if you want to treat it as a partially applied function
val s = sumOfCubes
         ^