1. 引言

在本教程中,我们将深入探讨 Scala 中的 偏函数(Partial Function)
偏函数是一种只对定义域的子集适用的函数

举个例子:我们可以定义一个作用于 Int 类型的函数,但它只处理奇数。

2. 理解偏函数的定义

查看 Scala 官方文档,偏函数有以下三个关键特性:

  • ✅ 是一元操作(只接受一个参数)
  • ✅ 仅适用于其定义域的一个子集
  • ✅ 可以显式定义 isDefinedAt 方法来判断是否适用,以及 apply 方法来执行逻辑

来看一个简单的偏函数示例:

val squareRoot: PartialFunction[Double, Double] = {
  def apply(x: Double) = Math.sqrt(x)
  def isDefinedAt(x: Double) = x >= 0
}

这个函数具备如下特点:

  • 接收一个 Double 类型参数
  • 仅适用于非负数(x >= 0
  • 显式定义了 isDefinedAtapply 方法

因此,它确实是一个偏函数。

⚠️ 实际开发中,isDefinedAtapply 通常是隐式定义的。我们可以使用 case 语句来简化写法:

val squareRootImplicit: PartialFunction[Double, Double] = {
  case x if x >= 0 => Math.sqrt(x)
}

如果我们对负数调用该函数,会抛出 scala.MatchError 运行时异常。

3. 使用 orElseandThen 进行链式调用

偏函数的强大之处在于可以链式组合。

假设我们要实现一个函数:正数变负数,负数或零变正数。虽然直接乘以 -1 就行了,但为了演示链式调用,我们拆成两个偏函数:

val negativeOrZeroToPositive: PartialFunction[Int, Int] = {
  case x if x <= 0 => Math.abs(x)
}

val positiveToNegative: PartialFunction[Int, Int] = {
  case x if x > 0 => -1 * x
}

然后使用 orElse 将它们组合:

val swapSign: PartialFunction[Int, Int] = {
  positiveToNegative orElse negativeOrZeroToPositive
}

此外,还可以使用 andThen 来串联后续处理逻辑。比如:

val printIfPositive: PartialFunction[Int, Unit] = {
  case x if x > 0 => println(s"$x is positive!")
}

然后链式调用:

(swapSign andThen printIfPositive)(-1)

这样写出来的代码简洁清晰,逻辑一目了然。

4. 在集合中的使用

偏函数在处理集合时非常实用。主要有以下几个方法值得关注:

4.1. collectmapfilter

collect 方法会将偏函数应用到集合中满足条件的元素,并返回新集合

定义一个偏函数用于 collect

val parseRange: PartialFunction[Any, Int] = {
  case x: Int if x > 10 => x + 1
}
List(15, 3, "aString") collect { parseRange }

结果是 List(16),因为只有 15 满足类型为 Int 且大于 10。

⚠️ 如果我们用 map

List(15, 3, "aString") map { parseRange }

会抛出 scala.MatchError,因为 map 会尝试对所有元素应用函数,包括字符串。

再看 filtercollect 的区别:

List(1, 2) collect { case i: Int => i > 10 }
List(1, 2) filter { case i: Int => i > 10 }
  • collect 返回:List(false, false)
  • filter 返回:List()(空列表)

注意,这里我们用的是匿名函数形式定义的偏函数。

5. 总结

本文讲解了 Scala 中的偏函数,展示了如何通过 orElseandThen 进行链式调用,以及如何在集合操作中使用 collectmapfilter

✅ 偏函数在构建高可组合性代码时非常有用,尤其是在处理数据转换和集合操作时。

合理使用偏函数,可以让代码更加简洁、健壮、易读。

如需查看完整代码,欢迎访问:GitHub 项目地址


原始标题:Partial Functions in Scala

» 下一篇: ScalaTest 入门指南