4.4. 序列(Sequences)
高阶函数的使用是序列处理时的一个普遍特点。Scala类库定义了几种不同类型的序列:数组(arrays)、列表(lists)、流(streams)和迭代器(iterators)。所有的序列都继承自特征(trait):Scala.Seq;从而都定义了一套方法使得相应处理更简介、高效。例如:map方法将一个函数应用于一个序列的所有元素,产生一个以相应结果为元素的序列。另一个例子是filter方法,将一个断言(predicate)函数应用于所有的元素,产生一个由所有使该断言为真的元素组成的序列。
下面这个sqrts函数展示了上述两个方法的使用,它以一个双精度浮点数的列表xs为参数,返回一个以其所有非负元素的平方根为元素的列表:
def sqrts(xs: List[double]): List[double] =
xs filter (0 <=) map Math.sqrt
注意,Math.sqrt是一个Java函数,但它可以与Scala定义的函数一样的方式作为参数传递给高阶函数。
4.5. For Comprehensions
Scala有一些特殊的语法用于更自然的表示某些特定的高阶函数的组合,其中for comprehensions就是对Haskell等语言中的list comprehensions进一步泛化。用for comprehensions写的sqrts如下:
def sqrts(xs: List[double]): List[double] =
for (val x <- xs; 0 <= x) yield Math.sqrt(x)
这里,val x <- xs是一个生成器(generator),产生一个序列,而0<=x是一个过滤器(filter),从前者产生的序列中根据某些条件过滤掉一些元素。这个comprehension返回另一个由yield子句所产生的数值构成的序列。一个comprehension可以有多个生成器。
For comprehension对应于map、flatMap和filter等高阶方法的组合,上面这个使用for comprehension实现的sqrts与4.4节那个实现是相同的。
For comprehension的主要优势在于它并不受特定数据类型的限制,任何定义了map、flatMap和filter方法的类型都可以使用它,包括所有序列类型(注2)、选项值(optional values)和数据库接口以及一些其他类型。用户还可以将for comprehension用于自定义类型,只要定义和实现了相关方法。
在Scala中,For循环与comprehensions类似,对应于foreach和filter的组合。例如:列表1当中的for循环:for (val arg <- args) ...对应于args foreach (arg => ...)。
注2数组类型尚未实现序列的全部方法,因为某些方法需要运行时类型,这一功能尚未实现