使用 HashMap 实现映射迭代器的函数的生命周期问题

Lifetime problems on implementing function that maps over an iterator using a HashMap

我尝试使用 HashMap:

实现映射迭代器的函数
use std::collections::HashMap;
use std::hash::Hash;

/// Translates every element it gets using a map. In case the map does not help, it is mapped to
/// itself.
fn translate<'a, 'b, S, T>(map: &'a HashMap<T, T>, stream: S) -> impl Iterator<Item = T> + 'a + 'b
where
    S: Iterator<Item = T> + 'b,
    T: Copy + Eq + Hash,
{
    stream.map(|e: T| -> T { *map.get(&e).unwrap_or(&e) })
}

playground

我收到此代码的错误消息:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/lib.rs:11:16
   |
11 |     stream.map(|e: T| -> T { *map.get(&e).unwrap_or(&e) })
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 6:14...
  --> src/lib.rs:6:14
   |
6  | fn translate<'a, 'b, S, T>(map: &'a HashMap<T, T>, stream: S) -> impl Iterator<Item = T> + 'a + 'b
   |              ^^
   = note: ...so that the types are compatible:
           expected &&std::collections::HashMap<T, T>
              found &&'a std::collections::HashMap<T, T>
note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 6:18...
  --> src/lib.rs:6:18
   |
6  | fn translate<'a, 'b, S, T>(map: &'a HashMap<T, T>, stream: S) -> impl Iterator<Item = T> + 'a + 'b
   |                  ^^
note: ...so that return value is valid for the call
  --> src/lib.rs:6:66
   |
6  | fn translate<'a, 'b, S, T>(map: &'a HashMap<T, T>, stream: S) -> impl Iterator<Item = T> + 'a + 'b
   |                                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我还没有弄清楚哪里出了问题,也不知道该如何解决。

我不得不猜测,因为您没有包含 MCVE。您的代码无法编译,表面上存在生命周期错误。您可能指的函数签名是:

fn translate<'a, 'b, S, T>(map: &'a HashMap<T, T>, stream: S) -> impl Iterator<Item = T> + 'a
where
    S: Iterator<Item = T> + 'b,
    T: Copy + Eq + Hash,
    'b: 'a, // Read: "'b outlives 'a"

因为 S 的寿命可能比您的 return 值长,而且它仍然有效。 但是,我看不出这种方法有任何优势:更长的生命周期始终有效,而不是更短的生命周期,您不需要明确指出这一点。只需使用一个生命周期,如下所示。

fn translate<'a, S, T>(map: &'a HashMap<T, T>, stream: S) -> impl Iterator<Item = T> + 'a
where
    S: Iterator<Item = T> + 'a,
    T: Copy + Eq + Hash,
{
    stream.map(move |e: T| -> T { *map.get(&e).unwrap_or(&e) })
}

如您所见,您还缺少 move 关键字,这是您的闭包绝对需要的。否则,它可能比函数拥有的地图寿命更长。

不过,这个函数还是比较密集的。如果你只在一个地方使用它,也许根本不介绍它,省去一些头痛?