gpt4 book ai didi

rust - 返回由闭包借用 self 产生的迭代器的函数的正确返回类型是什么

转载 作者:行者123 更新时间:2023-12-03 11:36:36 26 4
gpt4 key购买 nike

考虑以下代码,重点是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()
}
}
playground

关于rust - 返回由闭包借用 self 产生的迭代器的函数的正确返回类型是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65226641/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com