自动闭包
使用 @autoclosure 延迟表达式求值。
自动闭包 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
什么是自动闭包
@autoclosure 会自动将参数表达式包装进闭包,因此它直到函数实际使用它时才会求值。调用方只需写普通表达式,而不是闭包。
不使用自动闭包
通常,延迟求值需要在调用位置显式写出闭包:
func logIf(_ cond: Bool, _ message: () -> String) {
if cond { print(message()) }
}
logIf(true) { "expensive" } // caller writes braces使用自动闭包
@autoclosure 允许调用方传入一个不加包装的表达式:
func logIf(_ cond: Bool, _ message: @autoclosure () -> String) {
if cond { print(message()) }
}
logIf(true, "expensive") // no braces, evaluated only if cond延迟求值证明
只有在调用闭包时,表达式才会运行:
func pick(_ cond: Bool, _ value: @autoclosure () -> Int) -> Int {
cond ? value() : -1
}
func costly() -> Int { print("computed"); return 42 }
print(pick(false, costly())) // -1 -- "computed" never prints标准库的使用场景
&& 和 || 运算符、assert 以及 ?? 都使用自动闭包,因此右侧表达式只会在需要时求值。
像 ?? 一样短路
一个在不需要时跳过备用值的自定义默认值函数:
func orElse<T>(_ value: T?, _ fallback: @autoclosure () -> T) -> T {
value ?? fallback()
}
func makeDefault() -> Int { print("built"); return 0 }
print(orElse(5, makeDefault())) // 5 -- "built" never prints惰性的 assert 风格消息
只在检查失败时构建消息:
func check(_ cond: Bool, _ msg: @autoclosure () -> String) {
if !cond { print("FAIL: \(msg())") }
}
check(true, "this is never built")
check(false, "boom") // FAIL: boom自动闭包与逃逸
将其与 @escaping 组合,可以将延迟表达式存储起来供之后使用:
var thunks: [() -> Int] = []
func defer2(_ expr: @autoclosure @escaping () -> Int) {
thunks.append(expr)
}
defer2(1 + 1)
print(thunks[0]()) // 2 -- computed on demand让调用位置更清晰
这种优势纯粹来自语法:调用方写入一个值,而函数获得一个闭包:
func unless(_ cond: Bool, _ value: @autoclosure () -> String) -> String {
cond ? "skipped" : value()
}
print(unless(false, "shown")) // "shown"何时不应使用 NOT
自动闭包隐藏了参数其实是闭包这一事实,可能会让读者感到意外。请谨慎使用 — 只有在延迟求值确实有帮助时才使用,例如避免计算昂贵的默认值。
func first<T>(_ a: T?, _ b: @autoclosure () -> T) -> T { a ?? b() }
print(first(nil, 99)) // 99自动闭包不接受参数
自动闭包始终采用 () -> T 的形式 — 它包装单个表达式,不能接受参数:
func once(_ make: @autoclosure () -> [Int]) -> Int {
make().count
}
print(once([1, 2, 3])) // 3快速检查
@autoclosure 会对它的参数执行什么操作?
回顾
您已经了解了自动闭包:
@autoclosure会将参数表达式包装进() -> T闭包- 只有在函数调用该闭包时,表达式才会运行 — 这就是延迟求值
- 它为
&&、||、??和assert提供支持 - 与
@escaping组合即可进行存储;为了清晰起见,请谨慎使用
课程完成!下一步:Equatable、Hashable、Comparable。
常见问题解答
「自动闭包」课时是免费的吗?
是的 — 「自动闭包」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「自动闭包」这节课中我会学到什么?
使用 @autoclosure 延迟表达式求值。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「自动闭包」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。