【问题标题】:How do I return a reference to an iterator using conservative_impl_trait?如何使用conservative_impl_trait 返回对迭代器的引用?
【发布时间】:2020-01-29 06:59:25
【问题描述】:

我有一个petgraph::Graph 结构,我通过给每个节点权重一个parent_edge_idx 强加了一个树结构,这是从其父节点连接到自身的边的Option<EdgeIdx>

我需要遍历节点的子节点。我需要连接边的边权子节点的权重。

我想将该迭代分解为一个帮助函数,该函数返回对Iterator<Item = (EdgeIdx, NodeIdx)> 的引用。我想免费做这个;因为我必须借用self.search_tree才能做到这一点,所以迭代器只在self的生命周期内有效。

  1. 这是一个合理的函数吗?
  2. 可以写这个函数吗?

任何门控功能都可以;我每晚都在。

fn children<'a>(
    &'a mut self,
    node_idx: NodeIdx,
) -> &'a impl Iterator<Item = (EdgeIdx, NodeIdx)> {
    &self.search_tree.neighbors(node_idx).map(|child_idx| {
        let node = self.search_tree.node_weight(child_idx).unwrap();
        let edge_idx = node.parent_edge_idx.unwrap();
        (edge_idx, child_idx)
    })
}

【问题讨论】:

  • 试试impl Iterator&lt;Item = (EdgeIdx, NodeIdx)&gt; + 'a吧?
  • 如果您要使用高级的、不稳定的 Rust 功能,您可能应该已经熟悉 basic Rust 语言。你shouldn't be attempting to return references to variables created in functions because it can never work.
  • 请同时提供minimal reproducible example您的问题;这样做通常会在更短的时间内为您提供更优质的答案。
  • @masonk 答案相同在 SO 上将事物标记为重复项的重要部分。当一个问题被标记为重复时,该问题将永远存在,为您提到的那些确切的 Google 搜索提供路标。这些访问者最终来到这里,可以查看他们的问题是否与您的问题(或链接的问题)接近,然后可以阅读提供的答案。
  • 问题的缺失部分包括Self的完整定义。您请求任何潜在的回答者根据您提供的代码凭空创建的代码/工作量是巨大的——他们必须猜测所有类型应该是什么,存在哪些字段,哪些 crate 和确切的导入是必需的,他们必须创建一个驱动程序和数据来重现错误等。如果你edit你的问题包含这样的内容,我通常会在我关闭它时添加一条评论,将重复的答案应用于你的具体案例.

标签: rust petgraph


【解决方案1】:

in this question 已经介绍了如何返回迭代器。

  1. 注意你don't need to return a reference:你想直接返回一个迭代器value,所以如果我们删除方法体和返回类型中的第一个&amp;,那就更接近了我们需要的。

  2. 我们将使用impl Iterator,这样我们就不必准确地命名实际的迭代器类型。请注意(下面的代码)我们need to use the impl Iterator&lt;..&gt; + 'a syntax,这意味着(匿名)迭代器包含至少在'a 的生命周期内有效的引用。

  3. 我们不能在这里使用&amp;mut self!请注意,我们需要借用两次self.search_tree:一次用于.neighbors() 迭代器,一次用于map 闭包中使用的self.search_tree。多次借用与可变引用不兼容。

  4. 我们将move作为闭包的捕获模式,这样它就可以直接捕获self引用,而不是通过引用(这很重要,因为我们可以返回迭代器和闭包。

  5. Petgraph 专用,但我们将 g.node_weight(node_index).unwrap() 替换为等效的 &amp;g[node_index],但后者更易于阅读。

这里是您的代码的复制品,但对 1-5 进行了修改以使其编译:

#![feature(conservative_impl_trait)]
extern crate petgraph;

use petgraph::Graph;
use petgraph::graph::{NodeIndex, EdgeIndex};

struct Foo {
    search_tree: Graph<Node, i32>,
}

struct Node {
    parent_edge_idx: Option<EdgeIndex>,
}

impl Foo {
    fn children<'a>(&'a self, node_idx: NodeIndex)
        -> impl Iterator<Item = (EdgeIndex, NodeIndex)> + 'a
    {
        self.search_tree.neighbors(node_idx).map(move |child_idx| {
            let node = &self.search_tree[child_idx];
            let edge_idx = node.parent_edge_idx.unwrap();
            (edge_idx, child_idx)
        })
    }
}

【讨论】:

  • 谢谢你!我很困惑,因为我认为只有引用才能有生命周期,但看起来你在这里展示了一个拥有生命周期的类型。 Shepmaster 是绝对正确的,我错过了一些关于 Rust 生命周期的基本知识,我必须回去弄清楚。
  • @masonk Box&lt;Iterator&gt;impl Iterator 让您“忘记”迭代器背后的特定类型.. 但有一件事 Rust 永远不会让您忘记.. 这个值有多长有效使用! (一生!)。这就是它的短篇故事。
猜你喜欢
  • 2017-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 2021-05-09
  • 1970-01-01
  • 2018-01-12
相关资源
最近更新 更多