Rust如何从函数返回匿名闭包实现可递增计数器功能
解决方案
Rust中每个闭包都是独有的匿名类型,无法直接作为函数返回值的显式类型标注,需要通过闭包实现的Fn系列trait来抽象返回类型。你的计数器闭包需要修改内部捕获的变量,对应FnMut trait,有两种常用实现方式:
方案1:静态分发(推荐,零性能开销)
使用Rust 1.26版本后支持的返回位置impl Trait语法,静态分发没有堆分配开销,是优先选择的方案:
fn main() { println!("Hello, Rust!"); // 闭包需要修改内部状态,必须声明为mut let mut fn_closure = get_counter(); println!("closure returns: {}", fn_closure()); println!("closure returns: {}", fn_closure()); println!("closure returns: {}", fn_closure()); // 输出:1, 2, 3 符合预期 } fn get_counter() -> impl FnMut() -> i32 { let mut _i = 0; // move关键字将_i的所有权转移到闭包内,避免函数返回后变量被回收导致悬垂引用 move || -> i32 { _i += 1; _i } }
关键说明:
- 返回类型
impl FnMut() -> i32表示返回一个实现了无参数、返回i32的FnMut trait的类型,不需要写出闭包的具体匿名类型 move关键字是必须的:函数栈上的_i会在get_counter返回后被回收,必须将它的所有权转移到闭包中,才能保证闭包调用时访问的变量有效- 接收闭包的变量必须声明为
mut:因为调用FnMut类型的闭包会修改闭包内部的捕获变量,需要可变权限
方案2:动态分发(适合需要多态的场景)
如果需要把闭包存入集合、或者同一函数可能返回不同实现的闭包,可以用装箱的动态分发方案:
fn get_counter() -> Box<dyn FnMut() -> i32> { let mut _i = 0; Box::new(move || -> i32 { _i += 1; _i }) }
调用方式和方案1完全一致,仅会产生极少量的动态分发开销。
内容的提问来源于stack exchange,提问作者Alexandra Danith Ansley
相关产品推荐
相关产品推荐

