![Scala编程(第4版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/353/38381353/b_38381353.jpg)
9.2 简化调用方代码
前面这个例子展示了高阶函数如何帮助我们在实现API时减少代码重复的。高阶函数的另一个重要的用处是将高阶函数本身放在API当中来让调用方代码更加精简。Scala集合类型提供的特殊用途的循环方法是很好的例子。[1]它们当中很多都在第3章的表3.1中列出过,不过现在让我们再看一个例子来搞明白为什么这些方法是很有用的。
我们来看exists,这个方法用于判定某个集合是否包含传入的值。当然可以通过如下方式来查找元素:初始化一个var为false,用循环遍历整个集合检查每一项,如果发现要找的内容,就把var设为true。参考下面这段代码,判定传入的List是否包含负数:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-202-1.jpg?sign=1738761499-nQ6NKlR6SeusVDyZrux3yOVB6RBfI7p6-0-c283e5614d50ad3eb8652ef1959c4fd9)
如果你在解释器中定义了这个方法,可以这样来调用它:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-202-2.jpg?sign=1738761499-eTezjanFq6iLq9Am4w7qVCD4VCLRqX47-0-e3ac95018ef1eecea3759ab6b14cf385)
不过更精简的定义方式是对传入的List调用高阶函数exists,就像这样:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-202-3.jpg?sign=1738761499-m1MXPlubhsexDDTIQdrXuzUOTJBkkHjA-0-e77b8ce7ff2dfea20fadabc6bb495d36)
这个版本的containesNeg将交出跟之前一样的结果:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-203-1.jpg?sign=1738761499-3lxfdPKKMRvDvpR9gemfd5z9fiQdlw9E-0-f186a7a38da4ff773c97f7b3bfde08f3)
这个exists方法代表了一种控制抽象。这是Scala类库提供的一个特殊用途的循环结构,并不是像while或for那样是语言内建的。在前一节,高阶函数filesMatching帮助我们在对象FileMatcher的实现中减少了代码重复。这里的exists也带来了相似的好处,不过由于exists是Scala集合API中的公共函数,它减少的是API使用方的代码重复。如果没有exists,而又打算编写一个containsOdd方法来检查某个列表是否包含奇数,可能会这样写:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-203-2.jpg?sign=1738761499-0rE6wFsx8MA8bDM7yHu5FeM1tYUZuD78-0-0df3c37e1715b0b7ebe7c2643eaac48f)
如果对比containsNeg和containsOdd,你会发现所有的内容都是重复的,除了那个用于测试条件的if表达式。如果用exists,可以这样写:
![](https://epubservercos.yuewen.com/E8DF3B/20205397808551606/epubprivate/OEBPS/Images/40272-00-203-3.jpg?sign=1738761499-5EItbcXeiOzTgnprSMK0P80O4OIJE45l-0-3fdbc985be7e5172beaa7d96d1ba926f)
这个版本的代码体再一次跟对应的containsNeg方法一致(使用exists的版本),除了搜索条件不同。这里的重复代码要少得多,因为所有的循环逻辑都被抽象到exists方法里了。
Scala类库当中还有许多其他循环方法。跟exists一样,它们通常能帮助你缩短代码,如果你能找到机会使用它们。