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

宏基础

编译时生成代码

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

什么是宏?

宏是在编译期运行并生成其他代码的代码。Scala 3 宏可以检查参数、构建表达式,并在程序编译前将这些表达式输出到程序中。

Inline + Macro 模式

宏由 inline def 调用,并委托给使用 ${ ... } 标记的方法。内联定义是公共 API;宏实现则在编译器中运行。

import scala.quoted.*

inline def power(x: Double, inline n: Int): Double =
  ${ powerImpl('x, 'n) }

Quotes 上下文

每个宏实现都会接收一个隐式的 Quotes 上下文。它提供对反射 API 的访问,以及构建和拼接表达式的能力。

import scala.quoted.*

def powerImpl(x: Expr[Double], n: Expr[Int])(using Quotes): Expr[Double] =
  ???

Expr[T]

Expr[T] 将类型为 T 的类型化表达式表示为编译期数据。宏会接收并返回 Expr 值。

将值提升为 Expr

Expr(value) 会将宏中计算出的运行时值提升为表达式,以便拼接回代码中。任何具有 ToExpr 实例的类型都支持此操作。

import scala.quoted.*

def constImpl(using Quotes): Expr[Int] = Expr(42)

提取常量参数

当参数在静态上已知时,n.value(或 n.valueOrAbort)会从 Expr 中提取其背后的常量,使宏能够据此进行分支。

import scala.quoted.*

def powerImpl(x: Expr[Double], n: Expr[Int])(using Quotes): Expr[Double] = {
  val exp = n.valueOrAbort
  ??? // build x*x*...*x exp times
}

报告错误

当宏的前置条件不满足时,使用 quotes.reflect.report.errorAndAbort,并提供消息和位置,以生成编译错误。

import scala.quoted.*

def check(n: Expr[Int])(using q: Quotes): Expr[Int] = {
  import q.reflect.*
  val v = n.valueOrAbort
  if (v < 0) report.errorAndAbort("must be >= 0")
  Expr(v)
}

宏的存放位置

宏实现必须在使用它们的代码之前完成编译,通常位于单独的文件或模块中。编译器会在编译调用方时执行宏。

常见使用场景

宏可用于:

  • 类型类派生(JSON 编解码器等)
  • 编译期验证(正则表达式、SQL)
  • 捕获源代码位置的日志记录
  • 零开销抽象

安全性与卫生性

Scala 3 宏具有卫生性:生成的标识符不会意外捕获用户变量,并且类型系统会检查生成的代码,从而避免许多经典的宏错误。

运行时等价实现

在编译期计算幂的宏,与这个自包含的运行时版本会产生相同结果,但乘法已经由编译器直接嵌入代码中。

object Main {
  def power(x: Double, n: Int): Double =
    if (n == 0) 1.0 else x * power(x, n - 1)
  def main(args: Array[String]): Unit = {
    println(power(2.0, 3)) // 8.0
  }
}

快速检查

哪种类型表示宏接收和返回的类型化编译期表达式?

回顾

您学习了宏基础:

  • 宏通过 inline def ... ${ } 模式在编译期运行
  • Quotes 上下文和 Expr[T]
  • 使用 Expr(...) 提升值,并使用 .value 提取值
  • 错误报告和卫生性

下一节:引号与拼接。

常见问题解答

「宏基础」课时是免费的吗?

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

「宏基础」这节课中我会学到什么?

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

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

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