在第1章,咱們說過Scala容許你建立新的「感受像是原生語言支持」的控制抽象。儘管到目前你已經看到的例子都的確是控制抽象,不過任何人都不會 誤覺得它們是原生語言支持的。爲了搞明白如何讓控制抽象感受更像語言的擴展,你首先須要明白稱爲curry化的函數式編程技巧。 es6
51CTO編輯推薦:Scala編程語言專題 編程
curry化的函數被應用了多個參數列表,而不是僅僅一個。代碼9.2展現了一個規整的,未被curry化的函數,它實現兩個Int型參數,x和y的加法。 編程語言
- scala> def plainOldSum(x: Int, y: Int) = x + y
- plainOldSum: (Int,Int)Int
- scala> plainOldSum(1, 2)
- res4: Int = 3
代碼 9.2 定義和調用「陳舊的」函數 函數式編程
相對的,代碼9.3展現了curry化後的同一個函數。代之以一個列表的兩個Int參數,你把這個函數應用於兩個列表的各一個參數。 函數
- scala> def curriedSum(x: Int)(y: Int) = x + y
- curriedSum: (Int)(Int)Int
- scala> curriedSum(1)(2)
- res5: Int = 3
代碼 9.3 定義和調用curry化的函數 es5
這裏發生的事情是當你調用curriedSum,你實際上背靠背地調用了兩個傳統函數。第一個函數調用帶單個的名爲x的Int參數,並返回第二個函 數的函數值。第二個函數帶Int參數y。下面的名爲first的函數實質上執行了curriedSum的第一個傳統函數調用會作的事情: spa
- scala> def first(x: Int) = (y: Int) => x + y
- first: (Int)(Int) => Int
在第一個函數上應用1——換句話說,調用第一個函數並傳入1——會產生第二個函數: scala
- scala> val second = first(1)
- second: (Int) => Int = < function>
在第二個函數上應用2產生結果: code
- scala> second(2)
- res6: Int = 3
first和second函數只是curry化過程的一個演示。他們並不直接鏈接在curriedSum函數上。儘管如此,仍然有一個方式得到實際 指向curriedSum的「第二個」函數的參考。你能夠用偏應用函數表達式方式,把佔位符標註用在curriedSum裏,如: htm
- scala> val onePlus = curriedSum(1)_
- onePlus: (Int) => Int = < function>
curriedSum(1)_裏的下劃線是第二個參數列表的佔位符。前一章裏,當佔位符標註用在傳統方法上時,如println _,你必須在名稱和下劃線之間留一個空格。在這個例子裏不須要,由於println_是Scala裏合法的標識符,curriedSum(1)_不是。結果就是指向一個函數的參考,這個函數在被調用的時候,對它惟一的Int參數加一併返回結果:
- scala> onePlus(2)
- res7: Int = 3
而後如下是你如何得到對惟一的Int參數加二函數的方式:
- scala> val twoPlus = curriedSum(2)_
- twoPlus: (Int) => Int = < function>
- scala> twoPlus(2)
- res8: Int = 4