国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

減少Scala中的代碼重復(fù)

開發(fā) 后端
本文節(jié)選自Martin Odersky,Lex Spoon和Bill Venners所著,Regular翻譯的《Programming in Scala》的第九章。Scala是一種針對(duì) JVM 將函數(shù)和面向?qū)ο蠹夹g(shù)組合在一起的編程語(yǔ)言。

所有的函數(shù)都被分割成通用部分,它們?cè)诿看魏瘮?shù)調(diào)用中都相同,以及非通用部分,在不同的函數(shù)調(diào)用中可能會(huì)變化。通用部分是函數(shù)體,而非通用部分必須由參數(shù)提供。當(dāng)你把函數(shù)值用做參數(shù)時(shí),算法的非通用部分就是它代表的某些其它算法。在這種函數(shù)的每一次調(diào)用中,你都可以把不同的函數(shù)值作為參數(shù)傳入,于是被調(diào)用函數(shù)將在每次選用參數(shù)的時(shí)候調(diào)用傳入的函數(shù)值。這種高階函數(shù):higher-order function——帶其它函數(shù)做參數(shù)的函數(shù)——給了你額外的機(jī)會(huì)去組織和簡(jiǎn)化代碼。

51CTO編輯推薦:Scala編程語(yǔ)言專題

高階函數(shù)的一個(gè)好處是它們能讓你創(chuàng)造控制抽象從而使你減少代碼重復(fù)。例如,假設(shè)你正在寫一個(gè)文件瀏覽器,并且你想要提供一個(gè)API,能夠允許使用者搜索匹配某些標(biāo)準(zhǔn)的文件。首先,你加入了搜索文件名結(jié)束于特定字串的機(jī)制。這能讓你的用戶發(fā)現(xiàn),比方說(shuō),所有擴(kuò)展名為“.scala”的文件。你可以通過(guò)在單例對(duì)象中定義公開的filesEnding方法提供這樣的API,如:

  1. object FileMatcher {  
  2.  private def filesHere = (new java.io.File(".")).listFiles  
  3.  def filesEnding(query: String) =  
  4.   for (file < - filesHere; if file.getName.endsWith(query))  
  5.    yield file  
  6. }  
filesEnding方法通過(guò)使用私有幫助方法filesHere接受當(dāng)前目錄所有文件的列表,然后基于是否每個(gè)文件名以用戶特定的查詢結(jié)尾來(lái)過(guò)濾它們。由于filesHere是私有的,filesEnding方法是定義在你提供給你用戶的API,F(xiàn)ilesMatcher中唯一可以訪問(wèn)的方法。

目前為止還挺好,沒有重復(fù)的代碼。然而后來(lái),你決定讓別人可以基于文件名的任何部分做查詢。這個(gè)功能可以良好地用于以下情況:你的用戶記不住他們是以phb-important.doc,stupid-pub-report.doc,may2003salesdoc.phb,或什么完全不同的名字來(lái)命名文件的,但他們認(rèn)為“phb”出現(xiàn)在文件的什么地方。你回到工作并把這個(gè)函數(shù)加到你的API,F(xiàn)ileMatcher中:

  1. def filesContaining(query: String) =  
  2.  for (file < - filesHere; if file.getName.contains(query))  
  3.   yield file  
這段函數(shù)與filesEnding很像。它搜索filesHere,檢查名稱,并且如果名稱匹配則返回文件。唯一的差別是這個(gè)函數(shù)使用了contains替代endsWith。

隨著時(shí)間的推移,程序變得更加成功。最后,你屈服于幾個(gè)強(qiáng)勢(shì)用戶的需求,他們想要基于正則表達(dá)式搜索。這些馬虎的家伙擁有數(shù)千個(gè)文件的超大目錄,他們希望能做到像發(fā)現(xiàn)所有在題目中什么地方包含“oopsla”的“pdf”文件這樣的事。為了支持他們,你寫了這個(gè)函數(shù):

  1. def filesRegex(query: String) =  
  2.  for (file < - filesHere; if file.getName.matches(query))  
  3.   yield file  
有經(jīng)驗(yàn)的程序員會(huì)注意到所有的這些重復(fù)并想知道是否能從中提煉出通用的幫助函數(shù)。然而,顯而易見的方式不起作用。你希望能做的的是這樣的:

  1. def filesMatching(query: String, method) =  
  2.  for (file < - filesHere; if file.getName.method(query))  
  3.   yield file  
這種方式在某些動(dòng)態(tài)語(yǔ)言中能起作用,但Scala不允許在運(yùn)行期這樣粘合代碼。那么你該做什么呢?

函數(shù)值提供了一個(gè)答案。雖然你不能把方法名當(dāng)作值傳遞,但你可以通過(guò)傳遞為你調(diào)用方法的函數(shù)值達(dá)到同樣的效果。在這個(gè)例子里,你可以給方法添加一個(gè)matcher參數(shù),其唯一的目的就是針對(duì)查詢檢查文件名:

  1. def filesMatching(query: String,  
  2.   matcher: (String, String) => Boolean) = {  
  3.  for (file < - filesHere; if matcher(file.getName, query))  
  4.   yield file  
  5. }  
方法的這個(gè)版本中,if子句現(xiàn)在使用matcher針對(duì)查詢檢查文件名。更精確的說(shuō)法是這個(gè)檢查不依賴于matcher定義了什么。現(xiàn)在看一下matcher的類型。它是一個(gè)函數(shù),因此類型中有個(gè)=>。這個(gè)函數(shù)帶兩個(gè)字串參數(shù)——文件名和查詢——并返回布爾值,因此這個(gè)函數(shù)的類型是(String, String) => Boolean。

有了這個(gè)新的filesMatching幫助方法,你可以通過(guò)讓三個(gè)搜索方法調(diào)用它,并傳入合適的函數(shù)來(lái)簡(jiǎn)化它們:

  1. def filesEnding(query: String) =  
  2.  filesMatching(query, _.endsWith(_))  
  3. def filesContaining(query: String) =  
  4.  filesMatching(query, _.contains(_))  
  5. def filesRegex(query: String) =  
  6.  filesMatching(query, _.matches(_))  
這個(gè)例子中展示的函數(shù)文本使用了前一章中介紹的占位符語(yǔ)法,對(duì)你來(lái)說(shuō)可能感覺不是非常自然。因此,以下闡明例子里是如何使用占位符的。用在filesEnding方法里的函數(shù)文本_.endsWith(_),與下面的是一回事:

  1. (fileName: String, query: String) => fileName.endsWith(query) 
原因是filesMatching帶一個(gè)函數(shù),這個(gè)函數(shù)需要兩個(gè)String參數(shù),不過(guò)你不需要指定參數(shù)類型。因此,你也可以寫成(fileName, query) => fileName.endsWith(query)。由于第一個(gè)參數(shù),fileName,在方法體中被第一個(gè)使用,第二個(gè)參數(shù),query,第二個(gè)使用,你也可以使用占位符語(yǔ)法:_.endsWith(_)。第一個(gè)下劃線是第一個(gè)參數(shù),文件名的占位符,第二個(gè)下劃線是第二個(gè)參數(shù),查詢字串的占位符。

代碼已經(jīng)被簡(jiǎn)化了,但它實(shí)際還能更短。注意到query傳遞給了filesMatching,但filesMatching沒有用查詢做任何事只是把它傳回給傳入的matcher函數(shù)。這個(gè)傳來(lái)傳去的過(guò)程不是必需的,因?yàn)檎{(diào)用者在前面就已經(jīng)知道了query的內(nèi)容。你可以同樣從filesMatching和matcher中簡(jiǎn)單地去除query參數(shù),因此簡(jiǎn)化后的代碼如展示在代碼9.1中那樣。

  1. object FileMatcher {  
  2.  private def filesHere = (new java.io.File(".")).listFiles  
  3.  private def filesMatching(matcher: String => Boolean) =  
  4.   for (file < - filesHere; if matcher(file.getName))  
  5.    yield file  
  6.  def filesEnding(query: String) =  
  7.   filesMatching(_.endsWith(query))  
  8.  def filesContaining(query: String) =  
  9.   filesMatching(_.contains(query))  
  10.  def filesRegex(query: String) =  
  11.   filesMatching(_.matches(query))  
  12. }  
代碼 9.1 使用閉包減少代碼重復(fù)

這個(gè)例子演示了函數(shù)作為第一類值幫助你減少代碼重復(fù)的方式,如果沒有它們這將變得很困難。比方說(shuō)在Java里,你可以創(chuàng)建包括帶一個(gè)String并返回Boolean的方法的接口,然后創(chuàng)建并傳遞實(shí)現(xiàn)這個(gè)接口的匿名內(nèi)部類實(shí)例給filesMatching。盡管這個(gè)方式能去除你嘗試簡(jiǎn)化掉的代碼重復(fù),但同時(shí)它增加了許多乃至更多的新代碼。因此好處就不值這個(gè)開銷了,于是你或許就安于重復(fù)代碼的現(xiàn)狀了。

再者,這個(gè)例子還演示了閉包是如何能幫助你減少代碼重復(fù)的。前面一個(gè)例子里用到的函數(shù)文本,如_.endsWith(_)和_.contains(_),都是在運(yùn)行期實(shí)例化成函數(shù)值而不是閉包,因?yàn)樗鼈儧]有捕獲任何自由變量。舉例來(lái)說(shuō)表達(dá)式_.endsWith(_)里用的兩個(gè)變量,都是用下劃線代表的,也就是說(shuō)它們都是從傳遞給函數(shù)的參數(shù)獲得的。因此,_.endsWith(_)使用了兩個(gè)綁定變量,而不是自由變量。相對(duì)的,最近的例子里面用到的函數(shù)文本_.endsWith(query),包含一個(gè)綁定變量,下劃線代表的參數(shù),和一個(gè)名為query的自由變量。僅僅因?yàn)镾cala支持閉包才使得你可以在最近的這個(gè)例子里從filesMatching中去掉query參數(shù),從而更進(jìn)一步簡(jiǎn)化了代碼。

【相關(guān)閱讀】

  1. Scala:尾遞歸的跟蹤調(diào)用及其局限
  2. Scala允許的重復(fù)參數(shù)
  3. 學(xué)習(xí)Scala的閉包
  4. Scala的偏應(yīng)用函數(shù)
  5. Scala:函數(shù)文本的短格式和占位符語(yǔ)法

責(zé)任編輯:book05 來(lái)源: Artima
相關(guān)推薦

2009-07-22 07:43:00

Scala重復(fù)參數(shù)

2022-05-22 21:16:46

TypeScriptOmit 工具

2021-04-05 22:38:30

Python操作符代碼

2021-09-03 08:21:20

前端代碼模塊

2017-03-30 10:21:47

jsinspect前端代碼庫(kù)

2009-09-09 14:09:35

Scala Trait

2009-07-08 15:35:18

Case類Scala

2009-09-22 09:59:40

QueueCollecScala

2009-07-22 07:53:00

Scala擴(kuò)展類

2009-09-22 10:15:42

PersistentQScala

2009-07-22 07:47:00

Scala客戶代碼

2009-07-22 09:29:44

ScalaSpiral程序

2009-09-28 11:25:17

PersistentQKestrelScala

2009-07-21 17:21:57

Scala定義函數(shù)

2009-09-28 11:42:21

KestrelScala

2009-07-08 12:43:59

Scala ServlScala語(yǔ)言

2023-06-12 15:33:52

Scalafor循環(huán)語(yǔ)句

2022-03-08 14:02:35

GuavaMapjava

2021-12-16 16:35:46

CSS代碼前端

2020-10-31 17:33:18

Scala語(yǔ)言函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

国产成人久久精品| 国产一区久久| 成人av动漫在线| 97超级碰碰碰久久久| 日本成本人片免费观看| 欧美wwwww| 99re成人精品视频| 97视频热人人精品| 久久久久亚洲精品中文字幕| 日韩欧美国产一区二区三区| 日本在线成人一区二区| 日韩毛片视频| 午夜电影网亚洲视频| 99精品国产高清一区二区| 激情亚洲影院在线观看| 色综合天天综合| 男人的天堂99| 中文日产幕无线码一区二区| 久久婷婷色综合| 成人性生活视频免费看| 久久精品国产免费| 国产在线视频91| 亚洲永久视频| 91午夜理伦私人影院| 欧美偷拍自拍| 国产欧美精品一区二区三区介绍| 成人片免费看| 日韩精品久久久久久福利| 久久爱91午夜羞羞| 中文字幕国产亚洲| 精品福利在线| 日韩美女免费观看| 日韩中文视频| 精品99久久久久久| 2021国产在线| 亚洲国产精品久久91精品| 99国产精品免费网站| 国产日韩一区二区| 亚洲综合成人在线| 巨大黑人极品videos精品| 国产一区免费观看| 亚洲欧美一区二区三区国产精品| 鲁鲁在线中文| 国产精欧美一区二区三区| 激情综合亚洲精品| 性色av一区| 在线不卡国产精品| 一区二区毛片| 在线观看成人影院| 日韩精品在线电影| 国产精品88久久久久久| 国产精品极品美女在线观看免费 | 26uuu亚洲国产精品| 卡一卡二国产精品| 福利片在线看| 国产成人精品日本亚洲| 亚洲一区二区成人| 上原亚衣加勒比在线播放| 欧美xingq一区二区| 女同性一区二区三区人了人一 | 头脑特工队2免费完整版在线观看 头脑特工队2在线播放 | 韩日视频在线| 国产精品视频白浆免费视频| 亚洲免费在线看| 精品国产网站| 毛片在线免费| 免费成人av网站| 亚洲电影中文字幕| 亚洲国产日韩欧美一区二区三区| 蜜桃免费在线| 男人操女人免费软件| 在线播放国产一区二区三区| 久久久人成影片免费观看| 午夜精品一区二区在线观看| 欧美刺激午夜性久久久久久久| 成人av动漫| 九九九久久国产免费| 又黄又爽在线免费观看| 色婷婷一区二区| 亚洲伦理一区二区| 国产福利一区二区三区在线观看| 国产喷白浆一区二区三区| 国产成人免费| av高清在线免费观看| 国产欧美精品一区二区色综合| 福利一区二区三区视频在线观看| 午夜欧美性电影| 91福利视频在线观看| 成人性生交大片| 久久亚洲国产成人精品无码区| 中国色在线观看另类| 国产二区视频在线观看| 国产日产欧美精品| 处破女av一区二区| yiren22综合网成人| 国产精品九九久久久久久久| 高清久久久久久| 成人在线高清| 成人一对一视频| 一区二区三区 在线观看视| 99热国内精品| 亚州av中文字幕在线免费观看| 精品国产一区二区三区在线观看| 成+人+亚洲+综合天堂| 黄色激情在线播放| 青青青在线视频播放| 久久久中文字幕| 国产精品高潮呻吟| 北条麻妃在线一区二区免费播放 | 国产亚洲网站| 日日夜夜天天综合| 日本高清不卡一区二区三| 色屁屁一区二区| 欧美国产一区二区三区激情无套| 日本不卡1区2区3区| 久久久久欧美| 中文字幕欧美视频在线| 91社区在线播放| 国产一区亚洲| 欧美日韩大尺度| 久久久久999| 天天做天天摸天天爽国产一区| 日韩精品一级中文字幕精品视频免费观看 | 国产女人精品视频| 日韩av网址在线观看| 久国产精品韩国三级视频| 国产区视频在线观看| 久久女同互慰一区二区三区| 欧美大片网址| 日日躁夜夜躁aaaabbbb| 国产69精品久久久久久| 99久久777色| 少妇视频在线| 国精产品99永久一区一区| 免费在线日韩av| 日韩欧美一区二区视频在线播放| av网站免费线看精品| 毛片免费不卡| 国产白丝袜美女久久久久| 欧美高清不卡在线| 日本va欧美va瓶| 色8久久久久| 亚洲欧美日韩一级| 婷婷久久五月天| 欧美激情在线一区| 日韩一区二区久久久| 亚洲天堂2014| 成人激情文学综合网| 国内久久精品视频| 亚洲专区一区| 欧美男gay| 国产午夜亚洲精品一级在线| а√在线天堂官网| a天堂中文在线官网在线| 日本一二三区视频免费高清| 亚洲 欧美 日韩系列| 你懂的网址一区二区三区| 亚洲理论在线a中文字幕| 欧美日韩精品一区二区三区四区| 欧美性猛xxx| 6080午夜不卡| 男女男精品视频| 国产成人亚洲一区二区三区| 欧美xxxx黑人又粗又长密月| 久久国产精品电影| 欧美一区日韩一区| 韩日在线一区| 精品亚洲a∨| 欧美高清xxx| 91精品日本| 男人舔女人下面高潮视频| 成年人网站大全| 亚洲免费av一区二区三区| 国产无遮挡又黄又爽免费软件| 成人性a激情免费视频| 黄色三级在线观看| 在线看中文字幕| 国产一二区在线| 网站一区二区| 国产综合色在线观看| 黄频免费在线观看| www在线免费观看| 丁香花在线影院观看在线播放| 国产精品精品视频| 欧美激情一级精品国产| 欧美久久婷婷综合色| 久久黄色级2电影| 亚州国产精品| 四虎免费av| 国产精品电影久久久久电影网| 69堂精品视频| 久久97超碰色| 欧美日韩xxxx| 麻豆福利在线观看| 巨大荫蒂视频欧美大片| 伊人久久av导航| 久久精品magnetxturnbtih| 国产精品久久7| 色偷偷av亚洲男人的天堂| 欧美日韩国产在线观看|