简体   繁体   English

包装返回迭代器的 function 时的生命周期问题

[英]Lifetime issue when wrapping a function returning an Iterator

I am building a custom data structure which supposes to return an iterator for its elements.我正在构建一个自定义数据结构,它应该为其元素返回一个迭代器。 If simplified, it can look like this:如果简化,它可能看起来像这样:

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;
}

Now, in some cases, I would like to create a "wrapper" for this collection that transforms the elements returned by the iterator.现在,在某些情况下,我想为这个集合创建一个“包装器”,用于转换迭代器返回的元素。 For the sake of this example let's assume that this wrapper allows skipping over some elements of the original iterator:为了这个例子,我们假设这个包装器允许跳过原始迭代器的一些元素:

// 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)
}

Unfortunately, I get a compilation error when trying to use this code:不幸的是,尝试使用此代码时出现编译错误:

// 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());
}

I understand that StepWrapper<'a, A>::find_something requires self to be borrowed for the same lifetime as the original collection.我了解StepWrapper<'a, A>::find_something要求在与原始集合相同的生命周期内借用self But all my attempts to decouple lifetimes of a collection and a wrapper were unuseful.但是我所有将集合和包装器的生命周期解耦的尝试都是无用的。 Essentially a find_something function in the wrapper needs to return a result which outlives itself.本质上,包装器中的find_something function 需要返回一个超过自身寿命的结果。 Is there a way to express it in Rust?有没有办法用Rust来表达?

The pattern you're using is called a streaming iterator , and unfortunately it's not possible with the Iterator trait.您正在使用的模式称为流式迭代器,不幸的是,使用Iterator特征是不可能的。

This is a current weakness of Rust's type system: it lacks what are known as generic associated types, or GATs.这是 Rust 类型系统当前的一个弱点:它缺少所谓的泛型关联类型或 GAT。 There's an RFC for this language feature and a tracking issue . 此语言功能有一个 RFC和一个跟踪问题

In the meantime, the streaming_iterator crate is designed to provide the functionality you're looking for.同时, streaming_iterator crate旨在提供您正在寻找的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 返回对内部集合的引用时的迭代器生命周期问题 - Iterator lifetime issue when returning references to inner collection 实现Iterator时的生命周期问题 - Lifetime issue when implementing Iterator 在递归函数中链接本地迭代器时出现 Rust Lifetime 问题 - Rust Lifetime issue when chaining local iterator in recursive function 迭代器通过引用返回项目,生命周期问题 - Iterator returning items by reference, lifetime issue 从迭代器返回切片时无法推断适当的生命周期 - Cannot infer an appropriate lifetime when returning a slice from an iterator 如何在返回新接收的值和缓存值之间的所有组合的迭代器时修复生命周期问题? - How do I fix a lifetime issue when returning an iterator of all combinations between a newly received value and cached values? 方法返回迭代器的生命周期错误 - Lifetime error for method returning iterator 将迭代器映射到矩阵的元素时的生命周期问题 - Lifetime issue when mapping an iterator over elements of a matrix 返回具有相同生命周期的结构的迭代器的方法的生命周期 - Lifetimes for method returning iterator of structs with same lifetime 尝试在返回迭代器的闭包内改变状态时,Rust 错误“无法推断借用表达式的适当生命周期” - Rust error "cannot infer an appropriate lifetime for borrow expression" when attempting to mutate state inside a closure returning an Iterator
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM