如何解决嵌套迭代器上的 self 的生命周期问题“返回此值需要将 `*self` 借用于 `'a”
我正在尝试编写一个特征,它接收 Iter<Item = T>
的工作项、过滤器,然后应用任何未完成的内容,并记录结果。该特征包含一些状态(与外部服务的连接)。由于方法的定义是特征的一部分,返回类型是 Box<dyn Iter<Item = (Status,Work)>
的变体,作为对目前无法在特征中使用 -> impl Iterator
的让步。
我去掉了 trait DoesWork
以保持代码简单,但假设整个 impl OneKindOfRunner
是 impl DoesWork for OneKindOfRunner
,请(in the Rust playground):
struct OneKindOfRunner {
// conn: in reality this conn is mutable,and causes to need mut refs
// to the OneKindOfRunner. The WorkRunner keeps a state,and that is
// in a database backed by this conn,so work,filter and do_one_work
// all need to communicate with the database (hence self)
//
// I don't kNow if I can reasonably implement copy()
// as E0505 suggests,I prefer not right Now.
}
#[derive(Debug)]
struct Work {
// some static stuff,no mutable state,really.
}
type WorkStatus = (bool,Work); // does the work need to happen?
type WorkResult = (bool,Work); // did we do the work successfully?
// In the real app,OneKindOfRunner implements a Runner
// trait,hence the Box<>ed dyn return types.
impl OneKindOfRunner {
fn new() -> Self {
OneKindOfRunner {}
}
fn do_one_work<'a>(&'a mut self,work_item: Work) -> WorkResult {
(true,work_item) // return tuple indicating success or not (distinct from Result<T,E>)
}
fn filter_pending_work<'a>(
&'a mut self,work: impl Iterator<Item = Work> + 'a,) -> Box<dyn Iterator<Item = WorkResult> + 'a> {
Box::new(work.map(|w| (false,w)).into_iter())
}
fn work<'a>(
&'a mut self,) -> Result<Box<dyn Iterator<Item = WorkResult> + 'a>,()> {
Ok(Box::new(
self.filter_pending_work(work)
.map(move |(_status,work)| self.do_one_work(work))
.into_iter(),))
}
}
fn main() {
let work = vec![Work {},Work {},Work {}].into_iter();
let mut runner = OneKindOfRunner::new();
match runner.work(work) {
Ok(results) => {
for (success,work) in results {
println!("Result was {} for work {:?}",success,work)
}
}
Err(_) => panic!("something err'd"),};
}
error[E0505]: cannot move out of `self` because it is borrowed
--> src/main.rs:43:22
|
37 | fn work<'a>(
| -- lifetime `'a` defined here
...
41 | / Ok(Box::new(
42 | | self.filter_pending_work(work)
| | ---- borrow of `*self` occurs here
43 | | .map(move |(_status,work)| self.do_one_work(work))
| | ^^^^^^^^^^^^^^^^^^^^^^ ---- move occurs due to use in closure
| | |
| | move out of `self` occurs here
44 | | .into_iter(),45 | | ))
| |__________- returning this value requires that `*self` is borrowed for `'a`
无论是否使用 #43 上的 move
,我都找不到使这项工作起作用的方法。
我认为 &'a mut self
和 Result<Box<dyn Iterator<Item = WorkResult> + 'a>,()>
将确保结果的生命周期(这意味着对迭代器闭包的依赖?)与 self
(例如,我必须在允许 self
超出范围之前使用迭代器,无论是谁调用我的 work()
函数)
我认为问题出在使用 self.<some fn>
两次(嵌套),我不知道有什么好的替代方法。
实际上,我们不想消耗 Iter<Item = Work>
,并且能够干净地 map()
覆盖它一次。
fn work<'a>(
&'a mut self,()> {
Ok(Box::new(
self.filter_pending_work(work)
.map(move |(_status,work)| self.do_one_work(work))
.into_iter(),))
}
在框外分配 self.filter_pending_work(work)
的结果没有帮助,删除 move (_status,work)
会导致一些变化:
44 | | .map(|(_status,work)| self.do_one_work(work))
| | ^^^^^^^^^^^^^^^^^ ---- second borrow occurs due to use of `self` in closure
| | |
| | closure construction occurs here
45 | | .into_iter(),46 | | ))
| |__________- returning this value requires that `*self` is borrowed for `'a`
有什么合理的方法可以解决这个问题吗? Iterator
是在这里做的正确的事情,还是我应该放弃整个想法并使用 Box<Vec<Work>>
?感觉 Iterator<Item = Foo>
是更正确使用的东西,因为 Rust 强大的 API 用于过滤和映射,但尝试使用迭代器(而不是仅仅使用into_iter()
上的 Vec<T>
真的很痛苦。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。