考虑以下代码,重点是children_iter()
:
use std::collections::HashMap;
type NodeMap = HashMap<i32, Node>;
struct Node {
id: i32,
parent: Option<i32>,
sibling: Option<i32>,
children: Vec<i32>,
content: String,
}
pub struct NodeIterator<'a> {
nodes: &'a NodeMap,
current: &'a Node,
}
impl<'a> NodeIterator<'a> {
fn new(node: &'a Node, nodes: &'a NodeMap) -> NodeIterator<'a> {
NodeIterator {
nodes,
current: node,
}
}
pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
self.current
.children
.iter()
.map(|i| self.nodes.get(i).unwrap())
.map(|n| Self::new(n, self.nodes))
}
}
该代码的编译失败,并且:
error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
--> src/lib.rs:30:18
|
30 | .map(|i| self.nodes.get(i).unwrap())
| ^^^ ---- `self` is borrowed here
| |
| may outlive borrowed value `self`
|
note: closure is returned here
--> src/lib.rs:26:36
|
26 | pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
|
30 | .map(move |i| self.nodes.get(i).unwrap())
| ^^^^^^^^
error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
--> src/lib.rs:31:18
|
31 | .map(|n| Self::new(n, self.nodes))
| ^^^ ---- `self` is borrowed here
| |
| may outlive borrowed value `self`
|
note: closure is returned here
--> src/lib.rs:26:36
|
26 | pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
|
31 | .map(move |n| Self::new(n, self.nodes))
| ^^^^^^^^
有没有一种方法可以正确地指定生存期,以便很明显返回的迭代器仅在当前生存期内有效NodeIterator
?
您收到此错误的原因是因为在Rust中,迭代器是lazy-evaluated的。看起来您的闭包将在children_iter
函数中执行,但实际上直到调用者next
在返回的迭代器上调用方法后,闭包才真正执行。
编译器建议使用move
关键字将借用的引用移至闭包中,从而解决了该问题。但是,您也可以通过热切评估迭代器并将结果收集到中来解决此问题Vec<NodeIterator>
。这是固定和编译示例中的两种方法:
use std::collections::HashMap;
type NodeMap = HashMap<i32, Node>;
struct Node {
id: i32,
parent: Option<i32>,
sibling: Option<i32>,
children: Vec<i32>,
content: String,
}
pub struct NodeIterator<'a> {
nodes: &'a NodeMap,
current: &'a Node,
}
impl<'a> NodeIterator<'a> {
fn new(node: &'a Node, nodes: &'a NodeMap) -> NodeIterator<'a> {
NodeIterator {
nodes,
current: node,
}
}
pub fn children_iter(&self) -> impl Iterator<Item = NodeIterator> {
self.current
.children
.iter()
// lazily-evaluted closures
// they run in the caller's scope
.map(move |i| self.nodes.get(i).unwrap())
.map(move |n| Self::new(n, self.nodes))
}
pub fn children_iter_vec(&self) -> Vec<NodeIterator> {
self.current
.children
.iter()
// eagerly-evaluted closures
// we run them in the current scope
.map(|i| self.nodes.get(i).unwrap())
.map(|n| Self::new(n, self.nodes))
.collect()
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句