Scala 3 — 书籍

函数即值

语言

虽然每个已创建的编程语言可能都允许你编写纯函数,但第二个重要的 Scala FP 特性是你可以将函数创建为值,就像你创建 StringInt 值一样。

此特性有很多好处,最常见的好处是 (a) 你可以定义方法来接受函数参数,以及 (b) 你可以将函数作为参数传递到方法中。你已在此书中的多个地方看到过这一点,每当演示 mapfilter 等方法时

val nums = (1 to 10).toList

val doubles = nums.map(_ * 2)           // double each value
val lessThanFive = nums.filter(_ < 5)   // List(1,2,3,4)

在这些示例中,匿名函数被传递到 mapfilter 中。

匿名函数也称为lambda

除了将匿名函数传递到 filtermap 中之外,你还可以向它们提供方法

// two methods
def double(i: Int): Int = i * 2
def underFive(i: Int): Boolean = i < 5

// pass those methods into filter and map
val doubles = nums.filter(underFive).map(double)

将方法和函数视为值处理的能力是函数式编程语言提供的强大功能。

从技术上讲,将另一个函数作为输入参数的函数称为高阶函数。(如果你喜欢幽默,就像有人曾经写的那样,这就像说一个将另一个类的实例作为构造函数参数的类是一个高阶类。)

函数、匿名函数和方法

如你在那些示例中看到的那样,这是一个匿名函数

_ * 2

高阶函数讨论中所示,这是此语法的简写版本

(i: Int) => i * 2

像这样的函数被称为“匿名”,因为它们没有名称。如果你想给一个函数命名,只需将其分配给一个变量

val double = (i: Int) => i * 2

现在你有一个命名函数,它被分配给一个变量。你可以像使用一个方法一样使用这个函数

double(2)   // 4

在大多数情况下,double是函数还是方法并不重要;Scala 允许你以相同的方式对待它们。在幕后,Scala 技术允许你将方法像函数一样对待,称为Eta 扩展

将函数无缝地作为变量传递的能力是 Scala 等函数式编程语言的一个显著特征。正如你在本书中看到的mapfilter示例中一样,将函数传递到其他函数中的能力可以帮助你创建简洁且仍然可读的代码——富有表现力

如果你不习惯将函数作为参数传递到其他函数的过程,这里有一些你可以尝试的更多示例

List("bob", "joe").map(_.toUpperCase)   // List(BOB, JOE)
List("bob", "joe").map(_.capitalize)    // List(Bob, Joe)
List("plum", "banana").map(_.length)    // List(4, 6)

val fruits = List("apple", "pear")
fruits.map(_.toUpperCase)       // List(APPLE, PEAR)
fruits.flatMap(_.toUpperCase)   // List(A, P, P, L, E, P, E, A, R)

val nums = List(5, 1, 3, 11, 7)
nums.map(_ * 2)         // List(10, 2, 6, 22, 14)
nums.filter(_ > 3)      // List(5, 11, 7)
nums.takeWhile(_ < 6)   // List(5, 1, 3)
nums.sortWith(_ < _)    // List(1, 3, 5, 7, 11)
nums.sortWith(_ > _)    // List(11, 7, 5, 3, 1)

nums.takeWhile(_ < 6).sortWith(_ < _)   // List(1, 3, 5)

此页面的贡献者