0Pricing
Scala for Backend Engineering & Functional Programming · 课时

组合

andThen 与 compose

组合 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

组合函数

函数组合是指连接两个已有函数来构建新函数,使其中一个函数的输出成为下一个函数的输入。Scala 提供了 andThen 和 compose 来完成此操作。

object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val double = (x: Int) => x * 2
    val both = addOne andThen double
    println(both(5))
  }
}

andThen:从左到右

f andThen g 会先运行 f,再运行 g。从左到右阅读与执行顺序一致,许多人会觉得这种写法更直观。

  • (f andThen g)(x) == g(f(x))
object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val triple = (x: Int) => x * 3
    val pipeline = addOne andThen triple
    println(pipeline(4))  // (4 + 1) * 3
  }
}

compose:从右到左

f compose g 会先运行 g,再运行 f,这正是数学上的顺序 f(g(x))。

  • (f compose g)(x) == f(g(x))
object Main {
  def main(args: Array[String]): Unit = {
    val addOne = (x: Int) => x + 1
    val triple = (x: Int) => x * 3
    val pipeline = addOne compose triple
    println(pipeline(4))  // (4 * 3) + 1
  }
}

andThen 与 compose

二者互为镜像:

  • f andThen g = g compose f
  • f compose g = g andThen f

请根据具体情况选择读起来更自然的写法。

object Main {
  def main(args: Array[String]): Unit = {
    val f = (x: Int) => x + 10
    val g = (x: Int) => x * 2
    println((f andThen g)(3))
    println((g compose f)(3))
  }
}

串联多个函数

您可以重复使用 andThen 串联多个函数,构建一个从上到下流动的更长处理流程。

object Main {
  def main(args: Array[String]): Unit = {
    val clean = (s: String) => s.trim
    val lower = (s: String) => s.toLowerCase
    val bang  = (s: String) => s + "!"
    val process = clean andThen lower andThen bang
    println(process("  HELLO  "))
  }
}

组合会改变类型

进行组合的函数必须具有兼容的类型:第一个函数的输出类型必须与第二个函数的输入类型匹配。处理流程中的类型可以随之改变。

object Main {
  def main(args: Array[String]): Unit = {
    val length = (s: String) => s.length
    val isLong = (n: Int) => n > 5
    val check = length andThen isLong
    println(check("scala"))
    println(check("functional"))
  }
}

恒等函数

identity 返回未经任何改变的输入。它是组合运算的幺元:f andThen identity == f。在折叠和条件判断中,常可将其用作默认值。

object Main {
  def main(args: Array[String]): Unit = {
    val f = (x: Int) => x * 2
    val same = f andThen identity[Int]
    println(same(7))
  }
}

使用 reduce 进行组合

由于函数也是值,您可以将多个函数存储在列表中,然后使用 reduce 和 andThen 将它们全部组合起来。

object Main {
  def main(args: Array[String]): Unit = {
    val steps: List[Int => Int] = List(_ + 1, _ * 2, _ - 3)
    val pipeline = steps.reduce(_ andThen _)
    println(pipeline(5))  // ((5+1)*2)-3
  }
}

构建可复用的流水线

组合鼓励您编写功能单一的小函数,再将它们组装成更大的行为,这是函数式编程中的一个核心思想。

object Main {
  def main(args: Array[String]): Unit = {
    val sanitize = (s: String) => s.trim.toLowerCase
    val capitalize = (s: String) => s.capitalize
    val format = sanitize andThen capitalize
    println(format("  aLiCe "))
  }
}

使用 map 进行组合

组合后的函数仍然只是一个函数,因此您可以直接将它传给 map,让整个流水线作用于集合中的所有元素。

object Main {
  def main(args: Array[String]): Unit = {
    val transform = ((x: Int) => x + 1) andThen ((x: Int) => x * x)
    println(List(1, 2, 3).map(transform))
  }
}

仔细理解组合顺序

一个常见错误是混淆 andThen 和 compose。请始终记住:andThen = 先执行这个,再执行那个;compose = 顺序相反。

object Main {
  def main(args: Array[String]): Unit = {
    val inc = (x: Int) => x + 1
    val sqr = (x: Int) => x * x
    println((inc andThen sqr)(2))  // (2+1)^2 = 9
    println((inc compose sqr)(2))  // (2^2)+1 = 5
  }
}

快速检查

给定 f 和 g,(f andThen g)(x) 会计算什么?

回顾

您已经学会了函数组合:

  • f andThen g → g(f(x))(从左到右)
  • f compose g → f(g(x))(从右到左)
  • 它们互为镜像
  • identity 是幺元
  • 使用 reduce(_ andThen _) 组合函数列表

常见问题解答

「组合」课时是免费的吗?

是的 — 「组合」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。

「组合」这节课中我会学到什么?

andThen 与 compose 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「组合」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?

能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 作为值的函数
  2. 柯里化
  3. 组合
  4. 闭包
← 返回 Scala for Backend Engineering & Functional Programming