12-闭包表达式
2 分钟阅读
译文 · 基于 The Rust Reference
原文链接: https://doc.rust-lang.org/reference/expressions/closure-expr.html
r[expr.closure]
闭包表达式
r[expr.closure.syntax]
ClosureExpression ->
`async`?[^cl-async-edition]
`move`?
( `||` | `|` ClosureParameters? `|` )
(Expression | `->` TypeNoBounds BlockExpression)
ClosureParameters -> ClosureParam (`,` ClosureParam)* `,`?
ClosureParam -> OuterAttribute* PatternNoTopAlt ( `:` Type )?
r[expr.closure.intro]
闭包表达式也称 lambda 表达式或 lambda,它定义一种闭包类型并求值为该类型的值。闭包表达式的语法是:可选的 async 关键字、可选的 move 关键字,然后是由管道符(|)括起、以逗号分隔的模式列表(称为闭包参数,每个参数后可选择跟 : 和类型),然后是可选的 -> 和类型(称为返回类型),最后是一个表达式(称为闭包体操作数)。
r[expr.closure.param-type] 每个模式后可选的类型是该模式的类型注解。
r[expr.closure.explicit-type-body] 若存在返回类型,则闭包体必须是块。
r[expr.closure.parameter-restriction]
闭包表达式表示一个函数,把参数列表映射到参数之后的那个表达式。与 let 绑定一样,闭包参数是不可反驳模式,类型注解可选;若未给出,将从上下文推断。
r[expr.closure.unique-type] 每个闭包表达式都有唯一的匿名类型。
r[expr.closure.captures] 重要的是,闭包表达式会_捕获其环境_,而普通的函数定义不会。
r[expr.closure.capture-inference]
没有 move 关键字时,闭包表达式会推断它如何从环境中捕获每个变量,优先以共享引用捕获,相当于借用闭包体中提到的所有外部变量。
r[expr.closure.capture-mut-ref] 若有需要,编译器会转而推断应采用可变引用,或应从环境中移动或复制这些值(取决于其类型)。
r[expr.closure.capture-move]
可以在闭包前加上 move 关键字,强制通过复制或移动值来捕获环境。这常用于确保闭包的生命周期为 'static。
r[expr.closure.trait-impl]
闭包的 trait 实现
闭包类型实现哪些 trait 取决于变量如何被捕获、被捕获变量的类型,以及是否存在 async。关于闭包何时以及如何实现 Fn、FnMut 和 FnOnce,见调用 trait 与强制转换一章。若每个被捕获变量的类型也都实现了相应 trait,则闭包类型实现 Send 和 Sync。
r[expr.closure.async]
异步闭包
r[expr.closure.async.intro]
带 async 关键字的闭包表示它们是异步的,其方式与[异步函数][items.fn.async]类似。
r[expr.closure.async.future]
调用异步闭包并不会执行任何工作,而是求值为一个实现了 [Future]、对应于闭包体计算的值。
| |
r[expr.closure.async.edition2018]
[!EDITION-2018] 异步闭包从 Rust 2018 起才可用。
示例
本例中,我们定义函数 ten_times,它接受一个高阶函数参数,然后我们以闭包表达式作为参数调用它,接着再传入一个从环境中移出值的闭包表达式。
| |
闭包参数上的属性
r[expr.closure.param-attributes] 闭包参数上的属性遵循与普通函数参数相同的规则和限制。