稳定版Rust中如何实现返回引用的memoize函数?
稳定版Rust中实现无Clone约束记忆化函数的方案
首先明确:仅依靠标准库的Fn/FnMut trait,稳定版Rust无法实现你想要的签名。原因在于标准FnMut的call_mut方法签名限制:
pub trait FnMut<Args>: FnOnce<Args> { extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; }
这里的Self::Output是一个关联类型,无法与&mut self的生命周期绑定,所以闭包无法返回一个和自身内部缓存绑定的可变引用。
如果不想依赖不稳定特性,同时要避免Clone约束,唯一可行的方式是自定义结构体来封装缓存和闭包,而非使用匿名闭包。以下是具体实现:
use std::collections::HashMap; use std::hash::Hash; struct Memoized<K, V, F> { cache: HashMap<K, V>, func: F, } impl<K: Eq + Hash, V, F: FnMut(&K) -> V> Memoized<K, V, F> { fn new(func: F) -> Self { Self { cache: HashMap::new(), func, } } fn call(&'_ mut self, key: K) -> &'_ mut V { self.cache.entry(key).or_insert_with_key(|k| (self.func)(k)) } } // 辅助函数创建实例 fn memoize<K: Eq + Hash, V, F: FnMut(&K) -> V>(func: F) -> Memoized<K, V, F> { Memoized::new(func) }
使用方式示例:
fn main() { let mut compute = memoize(|k: &i32| k * 2); let val1 = compute.call(3); *val1 += 1; assert_eq!(*compute.call(3), 7); }
如果你坚持想要用闭包风格的返回值(即impl FnMut(K) -> &mut V),稳定版Rust暂时做不到——因为闭包的输出类型无法携带自身的生命周期。只能等待Fn trait的关联类型生命周期稳定(比如FnMut的Output支持依赖调用时的self生命周期),或者接受上述自定义结构体的方案。
内容的提问来源于stack exchange,提问作者Link0
相关产品推荐
相关产品推荐

