简体   繁体   English

封闭环境中的锈蚀寿命

[英]Rust lifetime in closure environment

I want to implement a graph structure in Rust. 我想在Rust中实现图结构。 For this goal, I wrote simple abstractions: 为此,我写了一些简单的抽象:

pub struct Graph<'a> {
    pub nodes: Vec<Node>,
    pub edges: Vec<Edge<'a>>,
}

#[derive(Debug)]
pub struct Node {
    pub id: String,
    pub label: String,
}

pub struct Edge<'a> {
    pub source: &'a Node,
    pub target: &'a Node,
}

Graph contains vectors of Nodes and Edges . Graph包含NodesEdges向量。 Every Edge has a ref to a Node in the same Graph . 每个Edge在同一Graph都有对Node的引用。

I don't know it's a possible write something like this. 我不知道有可能写这样的东西。

I tried to write a static method that builds a new Graph instance from a JSON representation: 我试图编写一个静态方法,该方法从JSON表示形式构建新的Graph实例:

impl<'a> Graph<'a> {
    pub fn from_json(json: &String) -> Graph {
        if let json::JsonValue::Object(deserialized) = json::parse(json.as_ref()).unwrap() {
            let nodes: Vec<Node> = deserialized
                .get("nodes")
                .unwrap()
                .members()
                .map(|v| {
                    if let json::JsonValue::Object(ref val) = *v {
                        return Node {
                            id: val.get("id").unwrap().to_string(),
                            label: val.get("label").unwrap().to_string(),
                        };
                    }
                    panic!("Invalid structure of json graph body.")
                })
                .collect::<Vec<Node>>();
            let edges: Vec<Edge> = deserialized
                .get("edges")
                .unwrap()
                .members()
                .map(|v| {
                    if let json::JsonValue::Object(ref val) = *v {
                        let source = (*nodes)
                            .iter()
                            .find(|&v| v.id == val.get("source").unwrap().to_string())
                            .unwrap();
                        let target = (*nodes)
                            .iter()
                            .find(|&v| v.id == val.get("target").unwrap().to_string())
                            .unwrap();
                        return Edge { source, target };
                    }
                    panic!("Invalid structure of json graph body.")
                })
                .collect::<Vec<Edge>>();
            return Graph { nodes, edges };
        }
        panic!("Incorrect struct of json contains!");
    }
}

When I compile, I get this error: 编译时,出现以下错误:

error[E0373]: closure may outlive the current function, but it borrows `nodes`, which is owned by the current function
  --> src/graph.rs:30:22
   |
30 |                 .map(|v| {
   |                      ^^^ may outlive borrowed value `nodes`
31 |                     if let json::JsonValue::Object(ref val) = *v {
32 |                         let source = (*nodes).iter().find(|&v| v.id ==  val.get("source").unwrap().to_string()).unwrap();
   |                                        ----- `nodes` is borrowed here
   |
help: to force the closure to take ownership of `nodes` (and any other referenced variables), use the `move` keyword
   |
30 |                 .map(move |v| {
   |                      ^^^^^^^^

error: aborting due to previous error

A possible solution to this problem is to add move before the closure parameters, but I need the nodes vector to build the Graph instance. 该问题的可能解决方案是在闭包参数之前添加move ,但是我需要nodes向量来构建Graph实例。

What am I doing wrong? 我究竟做错了什么?

After some research, I found this article's: Rust doc. 经过一番研究,我发现了这篇文章: Rust doc。 Smart pointers , Users Rust Lang , and I understood my mistakes. 智能指针用户Rust Lang ,我理解我的错误。 The first one: I remove lifetime parameters from structs definitions. 第一个:从结构定义中删除生命周期参数。

use std::rc::Rc;
#[derive(Debug)]
pub struct Graph {
    pub nodes: Vec<Rc<Node>>,
    pub edges: Vec<Edge>
}
#[derive(Debug)]
pub struct Node {
    pub id: String,
    pub label: String
}
#[derive(Debug)]
pub struct Edge {
    pub source: Rc<Node>,
    pub target: Rc<Node>
}

Second thing: I rewrote the code of from_json function for using Rc<T> instead of raw references. 第二件事:我重写了使用Rc<T>而不是原始引用的from_json函数的代码。

impl Graph {
    pub fn from_json(json: & String) -> Graph {
        if let json::JsonValue::Object(deserialized) = json::parse(json.as_ref()).unwrap() {
            let nodes : Vec<Rc<Node>> = deserialized.get("nodes").unwrap().members()
                .map(|v| {
                    if let json::JsonValue::Object(ref val) = *v {
                        return Rc::new(Node {
                            id: val.get("id").unwrap().to_string(),
                            label: val.get("label").unwrap().to_string()
                        });
                    }
                    panic!("Invalid structure of json graph body.")
            }).collect::<Vec<Rc<Node>>>();
            let edges : Vec<Edge> = deserialized.get("edges").unwrap().members()
                .map(|v| {
                    if let json::JsonValue::Object(ref val) = *v {
                        let source = nodes.iter().find(|&v| v.id ==  val.get("source").unwrap().to_string()).unwrap();
                        let target = nodes.iter().find(|&v| v.id ==  val.get("target").unwrap().to_string()).unwrap();
                        return Edge {
                            source: Rc::clone(&source),
                            target: Rc::clone(&target)
                        };
                    }
                    panic!("Invalid structure of json graph body.")
                }).collect::<Vec<Edge>>();
            return Graph {
                nodes,
                edges
            }
        }
        panic!("Incorrect struct of json contains!");
    }
}

Now it works. 现在可以了。 Thanks for sharing useful links. 感谢您分享有用的链接。 I found a lot of helpful information about building graph structs in Rust such as: Graph structure in Rust 我发现了很多有关在Rust构建图结构的有用信息,例如: Rust中的图结构

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM