第十二章 高阶函数
要点
- Scala中函数是“头等公民”,就和数字一样,可以在变量中存放函数
- 可以创建匿名函数,通常还会把它们交给其他函数
- 函数参数可以给出需要稍后执行的行为
- 许多集合方法都接受函数参数,将函数应用到集合中的值
- 很多语法上的简写可以让你以简短且易读的方式表达函数参数
闭包——在Scala中,可以在任何作用域内定义函数:包、类甚至是另一个函数或方法。在函数体内,可以访问相应作用域内的任何变量。并且函数可以在变量不再处于作用域内时被调用。
如def mulBy(factor: Double) = (x: Double) => factor * x //考虑如下调用 val triple = mulBy(3) val half = mulBy(0.5) println(triple(14) + " " + half(14)) //注意到每一个返回的函数都有自己的factor设置,这样的一个函数称为闭包,闭包由代码和代码用到的任何非局部变量定义构成。
柯里化指的是将原来接受两个参数的函数变成新的一个接受一个参数的过程。新的函数返回一个以原有第二个参数作为参数的函数。可以用柯里化来吧某个函数参数单拎出来,以提供更多用于类型推断的信息。
- 可以创建操作代码块的函数,它们看上去像内建的控制语句
第十三章 集合
要点
- 所有集合都扩展自Iterable特质
- 集合有三大类,分别为序列、集和映射
- 对于几乎所有集合类,Scala都同时提供了可变的和不可变的版本
- Scala列表要么是空的,要么有一头一尾,其中尾部本身又是一个列表
- 用LinkedHashSet来保留插入顺序,或者用SortedSet来按顺序迭代
- +将元素添加到无先后次序的集合中;+:和:+向前或向后追加到序列;++将两个集合串接在一起;-和–移除元素
map与flatmap。如果函数产出一个集合而不是单个值的话,可能会想将所有的值串接在一起。
val names = List("Peter", "Paul", "Mary") def ulcase(s: String) = Vector(s.toUpperCase(), s.toLowerCase()) //names.map(ulcase)得到List(Vector("PETER", "peter"), Vector("PAUL", "paul"), Vector("MARY", "mary")) //mames.flatMap(ulcase) 得到 List("PETER", "peter", "PAUL", "paul", "MARY", "mary")
- 化简折叠与扫描
- reduceLeft(op),从左到右依次执行op, (每次的运算结果与接下来的元素执行op)例如
List(1, 7, 2, 9).reduceLeft(_ - _) 得到 ((1 - 7) - 2 ) -9 = -17
而reduceRight将得到1 - (7 - (2 - 9)) = -13
foldLeft(init)(op)相似,不过是加了一个初始值 - 任意while循环都可以用折叠来替代。
- scanLeft和scanRight方法将折叠与映射操作结合在一起,可以得到包含所有中间结果的集合。
例如 (1 to 10).scanLeft(0)(_ + _)结果为Vector(0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55)
- reduceLeft(op),从左到右依次执行op, (每次的运算结果与接下来的元素执行op)例如
拉链操作
-zip将两个列表组合成一个列表,
val prices = List(5, 20)
val quantities = List(10, 2)
prices zip quantities 结果为List((5, 10), (20, 2))
如果一个集合比另一个短,那么结果中的对偶数量和较短的那个集合的元素的数量相同。- zipAll 方法可以指定较短列表的缺省值
- zipWithIndex方法返回对偶的列表,其中每个对偶中第二个组成部分是每个元素的下标,例如
“Scala”.zipWithIndex将得到
Vector((‘S’, 0), (‘c’, 1), (‘a’, 2), (‘l’, 3), (‘a’, 4))
- 迭代器,和Java相似