Rust闭包Trait选择逻辑疑问:为何选Fn而非FnOnce/FnMut?
Rust函数Trait选择问题解答
问题背景
给定以下Rust API定义:
pub struct Analyzer<F> { postprocess: F } impl<F: ___(i32) -> i32> Analyzer<F> { fn process(&self, n: i32) -> i32 { /* .. */ } pub fn pipeline(&self, n: i32) -> i32 { let n = self.process(n); (self.postprocess)(n) } }
问题:空白处最适合填入哪个函数Trait?选项包括:
FnOnce
FnMut
Fn
原解答
pipeline可能被多次调用,因此FnOnce不合适;pipeline接收self的不可变引用,若使用FnMut则无法在pipeline中调用,因此Fn是最适合的选择。
用户疑问
我们无法确定pipeline的调用次数,认为编译器基于此类假设做决策不合理,猜测Rust是通过其他机制得出该结论,现有解释只是恰好契合案例。
正确解释
其实核心和调用次数的“假设”无关,完全是Rust函数Trait的约束规则决定的:
FnOnce不可行:FnOnce的本质是调用时会消耗闭包自身(或其捕获的变量),但pipeline中是通过&self(不可变引用)访问postprocess,没有权限移动或消耗这个闭包,连一次调用都无法完成,更谈不上多次调用的问题。FnMut不可行:FnMut要求调用时必须持有闭包的可变引用(&mut F),因为它会修改捕获的变量。但pipeline的self是不可变引用,无法为postprocess提供可变访问权限,直接编译报错。Fn是最优解:Fn允许通过不可变引用调用闭包,完美匹配pipeline中&self访问postprocess的场景,同时它不限制调用次数,完全满足代码的语法和逻辑需求。
内容的提问来源于stack exchange,提问作者user1206899
相关产品推荐
相关产品推荐

