什么是函数的正确 return 类型 returning 一个用闭包借用 self 生成的迭代器
What is the correct return type of a function returning an iterator produced with a closure borrowing self
考虑以下代码并强调 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 中,迭代器是 延迟求值的 。看起来您的闭包将在 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()
}
}
考虑以下代码并强调 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 中,迭代器是 延迟求值的 。看起来您的闭包将在 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()
}
}