Scala學習:Curry化的函數

在第1章,咱們說過Scala容許你建立新的「感受像是原生語言支持」的控制抽象。儘管到目前你已經看到的例子都的確是控制抽象,不過任何人都不會 誤覺得它們是原生語言支持的。爲了搞明白如何讓控制抽象感受更像語言的擴展,你首先須要明白稱爲curry化的函數式編程技巧。 es6

51CTO編輯推薦:Scala編程語言專題 編程

curry化的函數被應用了多個參數列表,而不是僅僅一個。代碼9.2展現了一個規整的,未被curry化的函數,它實現兩個Int型參數,x和y的加法。 編程語言

 
  1. scala> def plainOldSum(x: Int, y: Int) = x + y  
  2. plainOldSum: (Int,Int)Int  
  3. scala> plainOldSum(12)  
  4. res4: Int = 3 

代碼 9.2 定義和調用「陳舊的」函數 函數式編程

相對的,代碼9.3展現了curry化後的同一個函數。代之以一個列表的兩個Int參數,你把這個函數應用於兩個列表的各一個參數。 函數

 
  1. scala> def curriedSum(x: Int)(y: Int) = x + y  
  2. curriedSum: (Int)(Int)Int  
  3. scala> curriedSum(1)(2)  
  4. res5: Int = 3 

代碼 9.3 定義和調用curry化的函數 es5

這裏發生的事情是當你調用curriedSum,你實際上背靠背地調用了兩個傳統函數。第一個函數調用帶單個的名爲x的Int參數,並返回第二個函 數的函數值。第二個函數帶Int參數y。下面的名爲first的函數實質上執行了curriedSum的第一個傳統函數調用會作的事情: spa

 
  1. scala> def first(x: Int) = (y: Int) => x + y  
  2. first: (Int)(Int) => Int  

在第一個函數上應用1——換句話說,調用第一個函數並傳入1——會產生第二個函數: scala

 
  1. scala> val second = first(1)  
  2. second: (Int) => Int = < function>  

在第二個函數上應用2產生結果: code

 
  1. scala> second(2)  
  2. res6: Int = 3 

first和second函數只是curry化過程的一個演示。他們並不直接鏈接在curriedSum函數上。儘管如此,仍然有一個方式得到實際 指向curriedSum的「第二個」函數的參考。你能夠用偏應用函數表達式方式,把佔位符標註用在curriedSum裏,如: htm

 
  1. scala> val onePlus = curriedSum(1)_  
  2. onePlus: (Int) => Int = < function>  

curriedSum(1)_裏的下劃線是第二個參數列表的佔位符。前一章裏,當佔位符標註用在傳統方法上時,如println _,你必須在名稱和下劃線之間留一個空格。在這個例子裏不須要,由於println_是Scala裏合法的標識符,curriedSum(1)_不是。結果就是指向一個函數的參考,這個函數在被調用的時候,對它惟一的Int參數加一併返回結果:

 
  1. scala> onePlus(2)  
  2. res7: Int = 3 

而後如下是你如何得到對惟一的Int參數加二函數的方式:

 
  1. scala> val twoPlus = curriedSum(2)_  
  2. twoPlus: (Int) => Int = < function>  
  3. scala> twoPlus(2)  
  4. res8: Int = 4
相關文章
相關標籤/搜索