Scala學(xué)習(xí):簡(jiǎn)化客戶代碼
9.2 前一個(gè)例子演示了高階函數(shù)能在你實(shí)現(xiàn)API的時(shí)候幫助減少代碼重復(fù)。高階函數(shù)的另一個(gè)重要應(yīng)用是把它們放在API里使客戶代碼更簡(jiǎn)潔。Scala的集合類型的特定用途循環(huán)方法提供了一個(gè)很好的例子。這些特定用途循環(huán)方法被定義在特質(zhì)Iterable中,被List,Set,Array,還有Map擴(kuò)展。很多已經(jīng)在第三章的表格3.1中列了出來(lái)。不過(guò)現(xiàn)在請(qǐng)注意其中的一個(gè)例子來(lái)看看為什么這些方法如此有用。
51CTO編輯推薦:Scala編程語(yǔ)言專題
考慮exists,一個(gè)判斷傳入的值是否包含在集合中的方法。當(dāng)然你也可以初始化一個(gè)var為假,循環(huán)遍歷集合類型,檢查每個(gè)元素,并且如果你找到了要尋找的就把var設(shè)置為真,通過(guò)這樣的方式尋找元素。以下是使用了這種方式的方法去判斷是否傳入的List包含了負(fù)數(shù)的例子:
假如你在解釋器里定義了這個(gè)方法,你就可以這樣調(diào)用:
- def containsNeg(nums: List[Int]): Boolean = {
- var exists = false
- for (num < - nums)
- if (num < 0)
- exists = true
- exists
- }
不過(guò)更簡(jiǎn)潔的定義這個(gè)方法的方式是通過(guò)在傳入的List上調(diào)用高階函數(shù)exists,如:
- scala> containsNeg(List(1, 2, 3, 4))
- res0: Boolean = false
- scala> containsNeg(List(1, 2, 3, -4))
- res1: Boolean = true
這個(gè)版本的containsNeg能產(chǎn)生和前面的那個(gè)一樣的結(jié)果:
- def containsNeg(nums: List[Int]) = nums.exists(_ < 0)
exists方法代表了控制抽象。是Scala庫(kù)提供的特定用途循環(huán)架構(gòu)而不是像while或for那樣內(nèi)建在Scala語(yǔ)言里的。上節(jié)中,高階函數(shù),filesMatching在對(duì)象FileMatcher的實(shí)現(xiàn)中減少了代碼重復(fù)。exists方法提供了類似的好處,但因?yàn)閑xists是公開在Scala的集合類型API里的,所以它減少的是API的客戶代碼中的重復(fù)。exists不存在的話,如果你想要寫一個(gè)containsOdd方法,檢測(cè)列表是否包含了奇數(shù),你或許會(huì)寫成這樣:
- scala> containsNeg(Nil)
- res2: Boolean = false
- scala> containsNeg(List(0, 1, -2))
- res3: Boolean = true
若你比較了containsNeg和containsOdd的函數(shù)體,你會(huì)發(fā)現(xiàn)除了if表達(dá)式之外,其它東西都是重復(fù)的。使用exists,你就可以這么寫:
- def containsOdd(nums: List[Int]): Boolean = {
- var exists = false
- for (num < - nums)
- if (num % 2 == 1)
- exists = true
- exists
- }
這個(gè)版本的代碼體再一次與相應(yīng)的containsNeg方法的保持一致(使用了exists的版本),除了搜索的條件不同。然而代碼重復(fù)的量卻少得多,因?yàn)樗械难h(huán)架構(gòu)都被提取成exists方法本身了。
- def containsOdd(nums: List[Int]) = nums.exists(_ % 2 == 1)
Scala的標(biāo)準(zhǔn)庫(kù)中還有許多其他循環(huán)方法。如果你能發(fā)現(xiàn)使用它們的機(jī)會(huì),那么像exists一樣,它們經(jīng)常能縮短你的代碼。
【相關(guān)閱讀】
- 減少Scala中的代碼重復(fù)
- Scala:尾遞歸的跟蹤調(diào)用及其局限
- Scala允許的重復(fù)參數(shù)
- 學(xué)習(xí)Scala的閉包
- Scala的偏應(yīng)用函數(shù)