Swift
宏
本文详细介绍了 Swift 中的宏,包括独立宏和附加宏的区别、宏的声明与实现,以及如何利用宏在编译时生成代码。
Swift 宏(Macros)允许你在编译时生成代码,从而减少重复代码并增强代码的表现力。宏会在编译源代码之前进行转换,将宏调用展开为生成的代码。
宏的分类
Swift 中的宏主要分为两类:
- 独立宏 (Freestanding Macros):独立出现,不依附于任何声明。
- 以
#开头调用。 - 例如:
#warning("This is a warning")
- 以
- 附加宏 (Attached Macros):修改或修饰与其附加的声明。
- 以
@开头调用。 - 例如:
@Observable
- 以
独立宏 (Freestanding Macros)
独立宏可以产生一个值,或者在编译时执行某些操作(如发出警告)。
func myFunction() {
print("Currently running \(#function)")
#warning("Something's wrong")
}附加宏 (Attached Macros)
附加宏为声明添加额外的功能。例如,@OptionSet 宏可以自动为结构体生成遵循 OptionSet 协议所需的代码。
@OptionSet
struct SundaeToppings {
private enum Options: Int {
case nuts
case cherry
case fudge
}
}展开后,SundaeToppings 结构体将自动包含 rawValue 初始化器、static var 属性等。
宏声明
宏的声明定义了宏的名称、参数以及它在何处可以使用。
@freestanding(expression)
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MyMacros", type: "StringifyMacro")@freestanding(expression):指定这是一个表达式类型的独立宏。#externalMacro:指定实现该宏的外部模块和类型。
宏实现
宏的实现通常在单独的 Swift Package 中,依赖 SwiftSyntax 库来操作抽象语法树(AST)。
public struct StringifyMacro: ExpressionMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) -> ExprSyntax {
guard let argument = node.argumentList.first?.expression else {
fatalError("compiler bug: the macro does not have any arguments")
}
return "(\(argument), \(literal: argument.description))"
}
}总结
Swift 宏通过在编译时生成代码,极大地提高了代码的灵活性和可维护性。无论是消除样板代码,还是构建强大的领域特定语言(DSL),宏都是一个强有力的工具。
在 GitHub 上编辑
上次更新于