如何延长 Rust 中迭代器适配器内临时变量的生命周期?
How can I extend the lifetime of a temporary variable inside of an iterator adaptor in Rust?
我有一个方法 make_iter()
可以在 Rust 中创建一个带有多个适配器的迭代器,它可以简化为以下 MCVE:
fn make_iter(first: &First) -> Box<dyn Iterator<Item = String> + '_> {
Box::new(first.make_objects().flat_map(|second| {
second
.iter()
.filter(|third| third.as_str() != "t2")
.flat_map(|third| vec![format!("{}.A", third), format!("{}.B", third)].into_iter())
.chain(
vec![
format!("{}.A", second.name()),
format!("{}.B", second.name()),
]
.into_iter(),
)
}))
}
pub fn main() {
let first = First {};
for i in make_iter(&first) {
println!("{}", i);
}
}
struct First {}
impl First {
fn make_objects(&self) -> Box<dyn Iterator<Item = Second> + '_> {
Box::new(
vec![
Second::new("s1".to_string()),
Second::new("s2".to_string()),
Second::new("s3".to_string()),
]
.into_iter(),
)
}
}
struct Second {
name: String,
objects: Vec<String>,
}
impl Second {
fn new(name: String) -> Second {
Second {
name,
objects: vec!["t1".to_string(), "t2".to_string(), "t3".to_string()],
}
}
fn name(&self) -> &str {
&self.name
}
fn iter(&self) -> Box<dyn Iterator<Item = &String> + '_> {
Box::new(self.objects.iter())
}
}
尝试编译此示例会产生生命周期错误:
error[E0597]: `second` does not live long enough
--> src/main.rs:3:9
|
3 | second
| ^^^^^^ borrowed value does not live long enough
...
14 | }))
| - `second` dropped here while still borrowed
这是可以理解的,因为 second
对象是一个临时对象,从同一个闭包返回的迭代器试图借用它,但失败了,因为 second
在闭包的末尾被删除了。
我的 objective 将延长此对象的生命周期,直到引用它的迭代器被删除,但我不知道如何。
请注意,无法更改结构实现。 Rust 版本为 1.34.2,2018 版
extend the lifetime of this object
你不能这样做,句号。这根本不是事情的运作方式。
另请参阅:
- Extending borrowed lifetime for String slice
- Is there any way to return a reference to a variable created in a function?
这是一个更简单的复制:
use std::iter;
fn example(outer: impl Iterator<Item = Inner>) {
outer.flat_map(|i| i.iter().map(|v| v.clone()));
}
struct Inner;
impl Inner {
fn iter(&self) -> impl Iterator<Item = &()> + '_ {
iter::empty()
}
}
既然你有不能改变的限制Inner
,最简单的解决办法就是更加急切和主动collect
:
fn example(outer: impl Iterator<Item = Inner>) {
outer.flat_map(|i| i.iter().map(|v| v.clone()).collect::<Vec<_>>());
}
我所知道的唯一避免这种情况的可能性是使用像 rental or owning_ref.
这样的板条箱
另请参阅:
- How can I store a Chars iterator in the same struct as the String it is iterating on?
如果你有可能改变 Inner
,你应该制作一个消费迭代器变体。然后该值不需要在闭包之外存在,因为迭代器已经取得了所有权。
use std::iter;
fn example(outer: impl Iterator<Item = Inner>) {
outer.flat_map(|i| i.into_iter().map(|v| v));
}
struct Inner;
impl Inner {
fn into_iter(self) -> impl Iterator<Item = ()> {
iter::empty()
}
}
我有一个方法 make_iter()
可以在 Rust 中创建一个带有多个适配器的迭代器,它可以简化为以下 MCVE:
fn make_iter(first: &First) -> Box<dyn Iterator<Item = String> + '_> {
Box::new(first.make_objects().flat_map(|second| {
second
.iter()
.filter(|third| third.as_str() != "t2")
.flat_map(|third| vec![format!("{}.A", third), format!("{}.B", third)].into_iter())
.chain(
vec![
format!("{}.A", second.name()),
format!("{}.B", second.name()),
]
.into_iter(),
)
}))
}
pub fn main() {
let first = First {};
for i in make_iter(&first) {
println!("{}", i);
}
}
struct First {}
impl First {
fn make_objects(&self) -> Box<dyn Iterator<Item = Second> + '_> {
Box::new(
vec![
Second::new("s1".to_string()),
Second::new("s2".to_string()),
Second::new("s3".to_string()),
]
.into_iter(),
)
}
}
struct Second {
name: String,
objects: Vec<String>,
}
impl Second {
fn new(name: String) -> Second {
Second {
name,
objects: vec!["t1".to_string(), "t2".to_string(), "t3".to_string()],
}
}
fn name(&self) -> &str {
&self.name
}
fn iter(&self) -> Box<dyn Iterator<Item = &String> + '_> {
Box::new(self.objects.iter())
}
}
尝试编译此示例会产生生命周期错误:
error[E0597]: `second` does not live long enough
--> src/main.rs:3:9
|
3 | second
| ^^^^^^ borrowed value does not live long enough
...
14 | }))
| - `second` dropped here while still borrowed
这是可以理解的,因为 second
对象是一个临时对象,从同一个闭包返回的迭代器试图借用它,但失败了,因为 second
在闭包的末尾被删除了。
我的 objective 将延长此对象的生命周期,直到引用它的迭代器被删除,但我不知道如何。
请注意,无法更改结构实现。 Rust 版本为 1.34.2,2018 版
extend the lifetime of this object
你不能这样做,句号。这根本不是事情的运作方式。
另请参阅:
- Extending borrowed lifetime for String slice
- Is there any way to return a reference to a variable created in a function?
这是一个更简单的复制:
use std::iter;
fn example(outer: impl Iterator<Item = Inner>) {
outer.flat_map(|i| i.iter().map(|v| v.clone()));
}
struct Inner;
impl Inner {
fn iter(&self) -> impl Iterator<Item = &()> + '_ {
iter::empty()
}
}
既然你有不能改变的限制Inner
,最简单的解决办法就是更加急切和主动collect
:
fn example(outer: impl Iterator<Item = Inner>) {
outer.flat_map(|i| i.iter().map(|v| v.clone()).collect::<Vec<_>>());
}
我所知道的唯一避免这种情况的可能性是使用像 rental or owning_ref.
这样的板条箱另请参阅:
- How can I store a Chars iterator in the same struct as the String it is iterating on?
如果你有可能改变 Inner
,你应该制作一个消费迭代器变体。然后该值不需要在闭包之外存在,因为迭代器已经取得了所有权。
use std::iter;
fn example(outer: impl Iterator<Item = Inner>) {
outer.flat_map(|i| i.into_iter().map(|v| v));
}
struct Inner;
impl Inner {
fn into_iter(self) -> impl Iterator<Item = ()> {
iter::empty()
}
}