返回引用的返回函数

  • 本文关键字:返回 函数 引用 rust
  • 更新时间 :
  • 英文 :


我想写一个简单的记忆函数

fn memoize<K: Eq + Hash, V: Clone>(mut func: impl FnMut(&K) -> V) -> impl FnMut(K) -> V {
let mut cache = HashMap::new();
|key| {
cache
.entry(key)
.or_insert_with_key(|k| func(k))
.clone()
}
}

Eq + Hash对参数的约束似乎是合理的,但Clone对返回值的约束似乎是不必要的。理想的签名是:

fn memoize<K: Eq + Hash, V>(mut func: impl FnMut(&K) -> V) -> impl FnMut(K) -> &mut V

需要指定返回引用的生命周期(有意义)。

理想情况下,&mut V应该与函数的ref一样存在(或类似的东西:&'a mut impl FnMut(K) -> &'a mut V)

因为Fn特征的impls是不稳定的,如果我想留在Fn特征(不写我的结构与一些fn call(&'a mut self, key: K) -> &'a mut V)有办法在稳定的Rust?

不幸的是,这是不可能的。即使手动实现FnMut也不可能,除非我们将Output设置为泛型关联类型:

pub trait GatifiedFnMut<Args: std::marker::Tuple> {
type Output<'a>
where
Self: 'a;
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output<'_>;
}
pub struct Memoized<K, V, F> {
cache: HashMap<K, V>,
func: F,
}
impl<K: Eq + Hash, V, F: FnMut(&K) -> V> GatifiedFnMut<(K,)> for Memoized<K, V, F> {
type Output<'a> = &'a mut V
where
Self: 'a;
extern "rust-call" fn call_mut(&mut self, (key,): (K,)) -> Self::Output<'_> {
self.cache.entry(key).or_insert_with_key(&mut self.func)
}
}

(注意:即使没有GATs,这也可以解决,但不能使用当前的FnOnce/FnMut/Fn特征,或者至少非常不舒服,见下面的链接问题)。

更多信息可在users.rust-lang.org上找到。

最新更新