包装返回迭代器的函数时的生命周期问题
Lifetime issue when wrapping a function returning an Iterator
我正在构建一个自定义数据结构,它假设 return 为其元素创建一个迭代器。如果简化,它可以看起来像这样:
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;
}
现在,在某些情况下,我想为此集合创建一个“包装器”,用于转换由迭代器 return 编辑的元素。为了这个例子,我们假设这个包装器允许跳过原始迭代器的一些元素:
// 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<'a, A>::find_something
要求 self
与原藏品的借阅期限相同。但是我所有试图解耦集合和包装器的生命周期的尝试都没有用。本质上,包装器中的 find_something
函数需要 return 一个比自身长寿的结果。有没有办法用 Rust 表达它?
您正在使用的模式称为 流式迭代器,不幸的是,Iterator
特征无法实现。
这是 Rust 类型系统当前的弱点:它缺少所谓的通用关联类型或 GAT。有一个 RFC for this language feature and a tracking issue.
与此同时,streaming_iterator
crate 旨在提供您正在寻找的功能。
我正在构建一个自定义数据结构,它假设 return 为其元素创建一个迭代器。如果简化,它可以看起来像这样:
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;
}
现在,在某些情况下,我想为此集合创建一个“包装器”,用于转换由迭代器 return 编辑的元素。为了这个例子,我们假设这个包装器允许跳过原始迭代器的一些元素:
// 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<'a, A>::find_something
要求 self
与原藏品的借阅期限相同。但是我所有试图解耦集合和包装器的生命周期的尝试都没有用。本质上,包装器中的 find_something
函数需要 return 一个比自身长寿的结果。有没有办法用 Rust 表达它?
您正在使用的模式称为 流式迭代器,不幸的是,Iterator
特征无法实现。
这是 Rust 类型系统当前的弱点:它缺少所谓的通用关联类型或 GAT。有一个 RFC for this language feature and a tracking issue.
与此同时,streaming_iterator
crate 旨在提供您正在寻找的功能。