Scala 3 — 书籍

不可变值

语言

在纯函数式编程中,只使用不可变值。在 Scala 中,这意味着

  • 所有变量都创建为 val 字段
  • 仅使用不可变集合类,例如 ListVector 以及不可变的 MapSet

仅使用不可变变量会引发一个有趣的问题:如果一切都是不可变的,那么如何改变任何东西?

在使用集合时,一个答案是你不改变现有集合;相反,你将函数应用于现有集合以创建一个新集合。这就是 mapfilter 等高阶函数的用武之地。

例如,假设你有一个名称列表(List[String]),它们都是小写的,并且你想查找所有以字母 "j" 开头的名称,然后你想将这些名称大写。在 FP 中,你可以编写此代码

val a = List("jane", "jon", "mary", "joe")
val b = a.filter(_.startsWith("j"))
         .map(_.capitalize)

如所示,你不改变原始列表 a。相反,你将过滤和转换函数应用于 a 以创建一个新集合,并将该结果分配给新的不可变变量 b

类似地,在 FP 中,你不创建具有可变 var 构造函数参数的类。也就是说,你不编写此代码

// don’t do this in FP
class Person(var firstName: String, var lastName: String)
             ---                    ---

相反,你通常会创建 case 类,其构造函数参数默认情况下为 val

case class Person(firstName: String, lastName: String)

现在,你创建一个 Person 实例作为 val 字段

val reginald = Person("Reginald", "Dwight")

然后,当你需要对数据进行更改时,使用 case 类附带的 copy 方法来“在进行复制时更新数据”,如下所示

val elton = reginald.copy(
  firstName = "Elton",   // update the first name
  lastName = "John"      // update the last name
)

还有其他处理不可变集合和变量的技术,但希望这些示例能让你了解这些技术。

根据你的需要,你可以创建枚举、特征或类,而不是 case 类。有关更多详细信息,请参阅 数据建模 章节。

本页面的贡献者