成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Scala的偏應用函數

開發 后端
本文節選自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻譯的《Programming in Scala》的第八章。Scala是一種針對 JVM 將函數和面向對象技術組合在一起的編程語言。

盡管前面的例子里下劃線替代的只是單個參數,你還可以使用一個下劃線替換整個參數列表。例如,寫成println(_),或者更好的方法你還可以寫成println _。下面是一個例子:

  1. someNumbers.foreach(println _)  

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

Scala把這種短格式直接看作是你輸入了下列代碼:

  1. someNumbers.foreach(x => println(x)) 
因此,這個例子中的下劃線不是單個參數的占位符。它是整個參數列表的占位符。請記住要在函數名和下劃線之間留一個空格,因為不這樣做編譯器會認為你是在說明一個不同的符號,比方說是,似乎不存在的名為println_的方法。

以這種方式使用下劃線時,你就正在寫一個偏應用函數:partially applied function。Scala里,當你調用函數,傳入任何需要的參數,你就是在把函數應用到參數上。如,給定下列函數:

  1. scala> def sum(a: Int, b: Int, c: Int) = a + b + c  
  2. sum: (Int,Int,Int)Int  
你就可以把函數sum應用到參數1,2和3上,如下:

  1. scala> sum(123)  
  2. res12: Int = 6 
偏應用函數是一種表達式,你不需要提供函數需要的所有參數。代之以僅提供部分,或不提供所需參數。比如,要創建不提供任何三個所需參數的調用sum的偏應用表達式,只要在“sum”之后放一個下劃線即可。然后可以把得到的函數存入變量。舉例如下:

  1. scala> val a = sum _  
  2. a: (Int, Int, Int) => Int = < function>  
有了這個代碼,Scala編譯器以偏應用函數表達式,sum _,實例化一個帶三個缺失整數參數的函數值,并把這個新的函數值的索引賦給變量a。當你把這個新函數值應用于三個參數之上時,它就轉回頭調用sum,并傳入這三個參數:

  1. scala> a(123)  
  2. res13: Int = 6 
實際發生的事情是這樣的:名為a的變量指向一個函數值對象。這個函數值是由Scala編譯器依照偏應用函數表達式sum _,自動產生的類的一個實例。編譯器產生的類有一個apply方法帶三個參數。產生的類擴展了特質Function3,定義了三個參數的apply方法。之所以帶三個參數是因為sum _表達式缺少的參數數量為三。Scala編譯器把表達式a(1,2,3)翻譯成對函數值的apply方法的調用,傳入三個參數1,2,3。因此a(1,2,3)是下列代碼的短格式:

  1. scala> a.apply(123)  
  2. res14: Int = 6 
Scala編譯器根據表達式sum _自動產生的類里的apply方法,簡單地把這三個缺失的參數前轉到sum,并返回結果。本例中apply調用了sum(1,2,3),并返回sum返回的,6。

這種一個下劃線代表全部參數列表的表達式的另一種用途,就是把它當作轉換def為函數值的方式。例如,如果你有一個本地函數,如sum(a: Int, b: Int, c: Int): Int,你可以把它“包裝”在apply方法具有同樣的參數列表和結果類型的函數值中。當你把這個函數值應用到某些參數上時,它依次把sum應用到同樣的參數,并返回結果。盡管不能把方法或嵌套函數賦值給變量,或當作參數傳遞給其它方法,但是如果你把方法或嵌套函數通過在名稱后面加一個下劃線的方式包裝在函數值中,就可以做到了。

現在,盡管sum _確實是一個偏應用函數,或許對你來說為什么這么稱呼并不是很明顯。這個名字源自于函數未被應用于它所有的參數。在sum _的例子里,它沒有應用于任何參數。不過還可以通過提供某些但不是全部需要的參數表達一個偏應用函數。舉例如下:

  1. scala> val b = sum(1, _: Int, 3)  
  2. b: (Int) => Int = < function> 
這個例子里,你提供了***個和***一個參數給sum,但中間參數缺失。因為僅有一個參數缺失,Scala編譯器會產生一個新的函數類,其apply方法帶一個參數。在使用一個參數調用的時候,這個產生的函數的apply方法調用sum,傳入1,傳遞給函數的參數,還有3。如下:

  1. scala> b(2)  
  2. res15: Int = 6 
這個例子里,b.apply調用了sum(1,2,3)。

  1. scala> b(5)  
  2. res16: Int = 9 
這個例子里,b.apply調用了sum(1,5,3)。

如果你正在寫一個省略所有參數的偏應用程序表達式,如println _或sum _,而且在代碼的那個地方正需要一個函數,你可以去掉下劃線從而表達得更簡明。例如,代之以打印輸出someNumbers里的每一個數字(定義在第113頁)的這種寫法:

  1. someNumbers.foreach(println _)  
你可以只是寫成:

  1. someNumbers.foreach(println)  
***一種格式僅在需要寫函數的地方,如例子中的foreach調用,才能使用。編譯器知道這種情況需要一個函數,因為foreach需要一個函數作為參數傳入。在不需要函數的情況下,嘗試使用這種格式將引發一個編譯錯誤。舉例如下:

  1. scala> val c = sum  
  2. < console>:5: error: missing arguments for method sum...  
  3. follow this method with `_' if you want to treat it as  
  4.  a partially applied function  
  5.  val c = sum  
  6.  ˆ  
  7. scala> val d = sum _  
  8. d: (Int, Int, Int) => Int = < function>  
  9. scala> d(102030)  
  10. res17: Int = 60 
為什么要使用尾下劃線?

Scala的偏應用函數語法凸顯了Scala與經典函數式語言如Haskell或ML之間,設計折中的差異。在經典函數式語言中,偏應用函數被當作普通的例子。更進一步,這些語言擁有非常嚴格的靜態類型系統能夠暴露出你在偏應用中可能犯的所有錯誤。Scala與指令式語言如Java關系近得多,在這些語言中沒有應用所有參數的方法會被認為是錯誤的。進一步說,子類型推斷的面向對象的傳統和全局的根類型接受一些被經典函數式語言認為是錯誤的程序。

舉例來說,如果你誤以為List的drop(n: Int)方法如tail(),那么你會忘記你需要傳遞給drop一個數字。你或許會寫,“println(drop)”。如果Scala采用偏應用函數在哪兒都OK的經典函數式傳統,這個代碼就將通過類型檢查。然而,你會驚奇地發現這個println語句打印的輸出將總是< function>!可能發生的事情是表達式drop將被看作是函數對象。因為println可以帶任何類型對象,這個代碼可以編譯通過,但產生出乎意料的結果。

為了避免這樣的情況,Scala需要你指定顯示省略的函數參數,盡管標志簡單到僅用一個‘_’。Scala允許你僅在需要函數類型的地方才能省略這個僅用的_。

【相關閱讀】

  1. Scala:函數文本的短格式和占位符語法
  2. 介紹Scala的***類函數
  3. Scala的本地函數:將私有方法轉換為本地方法
  4. Scala中定義函數的方法:method
  5. 繼續領悟函數式:Scala指令式風格代碼的重構

責任編輯:book05 來源: Artima
相關推薦

2017-03-07 15:13:28

Scala偏函數函數

2013-04-16 10:24:33

函數偏函數編程語言

2009-07-22 07:57:00

ScalaCurry化函數

2009-07-21 17:21:57

Scala定義函數

2009-12-11 10:44:00

Scala講座函數 scala

2010-01-28 14:51:24

Scala后函數式

2010-03-11 10:34:22

Scala

2009-06-16 17:09:17

Scala面向對象函數編程

2009-07-21 17:29:25

Scala第一類函數

2009-07-08 12:43:59

Scala ServlScala語言

2009-12-11 10:42:00

Scala講座類定義構造函數

2020-10-31 17:33:18

Scala語言函數

2010-09-14 15:34:41

Scala

2009-07-08 16:10:24

Scala簡介面向對象函數式

2009-07-22 07:41:00

Scala函數文本占位符語法

2009-09-27 15:29:00

Scala講座面向對象Scala

2009-07-09 00:25:00

Scala函數式

2009-06-17 13:26:06

scala繼承模型

2009-07-21 17:16:34

Scala函數式指令式

2009-12-11 10:43:00

Scala講座操作符函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久一区二区三区 | 日韩播放 | 男女羞羞免费视频 | 国产成人小视频 | 狠狠操狠狠操 | 欧美精品一区三区 | 亚洲人成人一区二区在线观看 | 欧美成视频 | 黄色毛片网站在线观看 | 亚洲成人精选 | hitomi一区二区三区精品 | 精品成人在线观看 | 色综合激情 | a级毛片基地 | 欧美在线精品一区 | av 一区二区三区 | 精品国产一区二区国模嫣然 | 国产精品一区二区在线播放 | 亚洲人成在线播放 | 日韩精品无码一区二区三区 | 午夜国产一级 | 亚洲视频免费 | 亚洲成人自拍网 | 久久久新视频 | 91 在线 | 欧美二区乱c黑人 | 久久国产精品色av免费观看 | 中文字幕一区二区三区在线视频 | 成人精品一区 | 国产一级在线 | a毛片| 中文字幕日韩专区 | 久久高清国产 | 91在线视频免费观看 | 欧美一二三四成人免费视频 | 天天插天天操 | 一区二区三区视频在线观看 | 日本在线网址 | 成年人黄色一级片 | 成人在线国产 | 久久久久九九九女人毛片 |