跳转到内容

Scala/高阶函数 1

来自维基教科书,开放世界中的开放书籍

高阶函数是接受函数作为参数或返回函数的函数。通过使用函数而不是更简单的值,高阶函数变得非常灵活。一个简单的例子是测试列表中至少一个元素是否通过某个测试。通过使用为 List 定义的现有高阶函数,我们无需编写测试每个元素的代码,而只需编写包含测试本身的函数。例如,假设我们想测试某个列表是否包含数字 4

def isEqualToFour(a:Int) = a == 4
val list = List(1, 2, 3, 4)
val resultExists4 = list.exists(isEqualToFour)
println(resultExists4) //Prints "true".

在上面的例子中,我们首先定义包含测试的函数(等于 4)。然后我们定义一个列表,它恰好包含数字 4(这意味着最终结果应该为真)。在第三行,我们调用方法“exists”,它接受包含测试的函数,将其应用于列表的元素,并返回该函数是否至少对其中一个元素为真。由于该列表确实包含 4,因此最终结果为真,这也是打印的结果。

如果我们想要测试列表中所有数字是否都等于 4(显然是假的),我们会使用“forall”方法。 "forall" 测试给定函数是否对列表中的每个元素都为真。

val resultForall4 = list.forall(isEqualToFour)
println(resultForall4) //Prints "false".

正如预期的那样,结果为假。注意,我们不必重新定义包含测试的函数。通过将测试分离到测试函数(“isEqualToFour”)中,并将应用测试函数的逻辑分离到高阶函数(“exists”和“forall”)中,我们避免了大量的重复。

另一个常见的高阶函数是“map”。假设你有一个数字列表,并希望独立地更改列表中的每个数字,例如将每个数字乘以某个常数。这正是“map”所做的:它接受一个转换函数,并将其独立地应用于每个元素以创建新的列表。让我们看看它的实际应用

def multiplyBy42(a:Int) = 42*a
val resultMultiplyBy42 = list.map(multiplyBy42)
println(resultMultiplyBy42) //Prints "List(42, 84, 126, 168)".

通过使用“map”,我们避免了将函数应用于每个元素并自己构建新列表。

除了 List 之外,还有许多其他高阶函数定义在大多数其他集合中,以及 Scala 库中的其他类中。一些值得注意的函数包括“reduce”和“foldLeft”/“foldRight”。

“reduce”接受一个函数,该函数接受两个元素并以某种方式将它们组合成一个相同类型的新元素,并一直这样做,直到只剩下一种结果元素。 "reduce" 的使用示例包括当你想要找到一些数字的总和或总积,或者想将许多字符串组合成一个字符串,也许是在后续字符串之间插入类似 "\n"、"," 或 ";" 之类的东西。

“foldLeft”/“foldRight”基本上是顺序转换。虽然“map”接受每个元素并独立地对其进行转换,但折叠会依次遍历集合,接受每个元素和之前的结果,并将其转换为新结果(例如新列表或总和)。折叠比“map”和“reduce”更难使用,但更灵活,实际上可以用来定义“map”和“reduce”本身。“Left”和“Right”指的是折叠遍历元素的方向。

华夏公益教科书