我想用 Rust 实现一个图形结构。为了这个目标,我写了简单的抽象:
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
包含Nodes
和Edges
的向量。每个 Edge
都有一个对同一 Graph
中的 Node
的引用。
我不知道是否可以这样写。
我尝试编写一个静态方法,从 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!");
}
}
当我编译时,我得到这个错误:
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
这个问题的一个可能的解决方案是在闭包参数之前添加move
,但我需要nodes
向量来构建Graph
实例.
我做错了什么?
最佳答案
经过一些研究,我发现这篇文章的:Rust doc. Smart pointers , Users Rust Lang ,我明白了我的错误。 第一个:我从结构定义中删除生命周期参数。
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>
}
第二件事:我重写了from_json
的代码使用 Rc<T>
的函数而不是原始引用。
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!");
}
}
现在可以了。感谢分享有用的链接。我在 Rust
中找到了很多关于构建图形结构的有用信息。如:Graph structure in Rust
关于闭包环境中的 Rust 生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48850807/