【问题标题】:Lifetime issue when wrapping a function returning an Iterator包装返回迭代器的函数时的生命周期问题
【发布时间】:2021-01-15 09:27:46
【问题描述】:

我正在构建一个自定义数据结构,它应该为其元素返回一个迭代器。如果简化,它可能看起来像这样:

use std::iter::{Iterator, StepBy};

// My collection which returns iterator to it's elements
pub trait MyCollection<'a, T: 'a> {
  type I: Iterator<Item = &'a T>;
  fn find_something(&'a self) -> Self::I;
}

现在,在某些情况下,我想为这个集合创建一个“包装器”,用于转换迭代器返回的元素。为了这个例子,我们假设这个包装器允许跳过原始迭代器的一些元素:

// Wrapper for a collection that allows iterating over elements with a step
pub struct StepWrapper<'a, A>(&'a A, usize);

impl<'a, T: 'a, A: MyCollection<'a, T>> MyCollection<'a, T> for StepWrapper<'a, A> {
  type I = StepBy<A::I>;
  fn find_something(&'a self) -> Self::I {
    self.0.find_something().step_by(self.1)
  }
}

// Function which takes a collection and a step value and returns a wrapped collection
fn wrap<'a, T: 'a, A: MyCollection<'a, T>>(a: &'a A, step: usize) -> impl MyCollection<'a, T> {
  StepWrapper(a, step)
}

很遗憾,在尝试使用此代码时出现编译错误:

// Example
impl<'a> MyCollection<'a, u64> for Vec<u64> {
  type I = std::slice::Iter<'a, u64>;
  fn find_something(&'a self) -> Self::I {
    return self.iter();
  }
}

fn main() {
  let collection = vec![12, 13, 14];
  let wrapped = wrap(&collection, 2);
  
  // Error now
  let result = wrapped.find_something().skip(1).next();
  //           ^^^^^^^ borrowed value does not live long enough

  println!("{}", result.unwrap());
}

我了解StepWrapper&lt;'a, A&gt;::find_something 要求self 的借用期限与原始收藏相同。但是我所有将集合和包装器的生命周期解耦的尝试都是无用的。本质上,包装器中的find_something 函数需要返回一个比它本身寿命更长的结果。有没有办法用 Rust 来表达?

【问题讨论】:

  • 修复了代码。当我从self 中删除生命周期'a 时,impl&lt;'a&gt; MyCollection&lt;'a, u64&gt; for Vec&lt;u64&gt; 出现错误。
  • 在 Rust 中,包装不是引用而是整个对象(按值)更容易,从而消除了处理引用的所有痛苦。如果您需要获取内部值,您可以实现这样的方法来解包它(通过引用或通过值)。

标签: rust iterator traits lifetime


【解决方案1】:

您使用的模式称为流式迭代器,不幸的是,Iterator trait 无法实现。

这是 Rust 类型系统当前的一个弱点:它缺少所谓的泛型关联类型或 GAT。有一个RFC for this language feature 和一个tracking issue

与此同时,streaming_iterator crate 旨在提供您正在寻找的功能。

【讨论】:

    猜你喜欢
    • 2015-11-15
    • 2014-08-25
    • 2020-07-02
    • 2015-04-30
    • 2020-07-26
    • 2021-05-31
    相关资源
    最近更新 更多