宏基础
编译时生成代码
宏基础 是 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 反馈 — 无需本地设置。