日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
引入Option優(yōu)雅地保證健壯性

REA的Ken Scambler在其演講《2 Year of Real World FP at REA》中,總結(jié)了選擇函數(shù)式編程的三個原因:Modularity, Abstraction和Composability。

創(chuàng)新互聯(lián)專注于企業(yè)營銷型網(wǎng)站建設(shè)、網(wǎng)站重做改版、河?xùn)|網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5網(wǎng)站設(shè)計、購物商城網(wǎng)站建設(shè)、集團公司官網(wǎng)建設(shè)、外貿(mào)營銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為河?xùn)|等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

函數(shù)式編程強調(diào)純函數(shù)(Pure Function),這是模塊化的一個重要基礎(chǔ),因為對于純函數(shù)而言,可以不用考慮調(diào)用的上下文,就可以根據(jù)函數(shù)的輸入推斷函數(shù)的執(zhí)行結(jié)果。這也就是Ken所謂的:

 You can tell what it does without Looking at surrounding context.

Ken在演講中給出了一個案例:

 
 
  1. def parseLocation(str: String): Location = { 
  2.   val parts = str.split(",") 
  3.   val secondStr = parts(1) 
  4.   val parts2 = secondStr.split(" ") 
  5.   Location(parts(0), parts2(0), parts(1).toInt)} 

仔細閱讀這段代碼,你會發(fā)現(xiàn)這段代碼是不健壯的,可能存在如下錯誤:

  • 作為input的str可能為null
  • parts(0)和parts(1)可能導(dǎo)致索引越界
  • parts2(0)可能導(dǎo)致索引越界
  • parts(1)未必是整數(shù),調(diào)用toInt可能導(dǎo)致類型轉(zhuǎn)換異常

這段代碼隱含的錯誤還可能被廣泛地蔓延到系統(tǒng)的其他地方,只要該函數(shù)被調(diào)用。這種蔓延可能會因為更多嵌套的調(diào)用而產(chǎn)生級聯(lián)的錯誤效應(yīng)。例如:

 
 
  1. def doSomethingElse(): Unit = { 
  2.   // ...Do other stuff 
  3.   parseLocation("Melbourne, VIC 3000")} 

而doSomethingElse()函數(shù)又被其他函數(shù)調(diào)用,這些潛在的缺陷會分布到各個直接或間接的調(diào)用點。這意味著代碼會繼承它所調(diào)用代碼的錯誤以及副作用,使得對代碼功能的推理(reasoning)變得近乎不可能,更不用說代碼的模塊化(modularity)了。

我們當(dāng)然可以通過對null進行檢測來避免出現(xiàn)這些錯誤。然而看看各種出現(xiàn)null值的可能分支,需要我們做各種條件判斷,想象這樣的代碼都讓人不寒而栗。引入Option類型就可以很好地封裝這種可能性。按照Ken的說法就是:

 All possibilities have been elevated into the type system.
 
 
  1. def parseLocation(str: String): Option[Location] = { 
  2.  val parts = str.split(",") 
  3.  for { 
  4.    locality <- parts.optGet(0) 
  5.    theRestStr <- parts.optGet(1) 
  6.    theRest = theRestStr.split(" ") 
  7.    subdivision <- theRest.optGet(0) 
  8.    postcodeStr <- theRest.optGet(1) 
  9.    postcode <- postcodeStr.optToInt 
  10.  } yield Location(locality, subdivision, postcode)} 

以上代碼中,split()函數(shù)返回的類型為Array[String],該類型自身是沒有optGet()函數(shù)的。但是我們可以為Array[String]定義隱式轉(zhuǎn)換:

 
 
  1. implicit class StringArrayWrapper(array: Array[String]) { 
  2.     def optGet(index:Int): Option[String] = { 
  3.         if (array.length > index) Some(array(index)) else None 
  4.     }} 

optToInt方法可以如法炮制。

Ken的解決方案并沒有考慮到parseLocation函數(shù)入?yún)tr存在null值的可能,故而在對str調(diào)用split方法時仍然有可能導(dǎo)致拋出空指針異常。因此進一步,我們還可以修改parseLocation函數(shù)的定義:

 
 
  1. def parseLocation(optStr: Option[String]): Option[Location] 

顯然,通過引入Option,既規(guī)避了前面分析可能出現(xiàn)的錯誤,又能避免編寫繁瑣的if判斷。這里的關(guān)鍵點是Option對兩種可能性(None與Some)的封裝。它由兩個代數(shù)類型Some與None構(gòu)成,前者包含了一個值,而后者則包含了一個不存在的值。事實上,Option是一個Maybe Monad,實現(xiàn)了flatMap與filter,因而在Scala中可以用for comprehension來訪問。

【本文為專欄作者“張逸”原創(chuàng)稿件,轉(zhuǎn)載請聯(lián)系原作者】


網(wǎng)頁名稱:引入Option優(yōu)雅地保證健壯性
文章位置:http://www.dlmjj.cn/article/djocpso.html