Petgraph 是一个很酷的 Rust 库,用于处理图形。例如。通过标记为 2024 的箭头连接的两个节点
digraph { // Graphviz DOT syntax
a [ label = "A" ]
b [ label = "B" ]
a -> b [ label = "2024" ]
}
将被写成(通过内部通用节点和边类型的 add 方法进行类型推断):
use petgraph::graph::Graph;
let mut graph = Graph::new(); // Graph::<&str, i32>::new();
let a = graph.add_node("A");
let b = graph.add_node("B");
graph.add_edge(a, b, 2024);
现在我想将其(从更大的用例缩小范围)打包到宏中。由于 Petgraph 有各种图的实现,我想参数化确切的类型:
use petgraph::stable_graph::StableGraph;
macro_rules! graph {
($type:ty) => {{
let mut graph = $type::new();
let a = graph.add_node("A");
let b = graph.add_node("B");
graph.add_edge(a, b, 2024);
graph
}}
}
let g = graph!(StableGraph);
这个
$type::new()
给出了不以标识符开头的类型需要在限定路径中用尖括号括起来:<
,>
以及我是否这样做添加缺少的通用参数:<N, E>
这可行,但失去了内部类型的巧妙推理:
let mut graph = <$type>::new();
…
let g = graph!(StableGraph<&str, i32>);
我也尝试过
$type:path
,但面临着几乎相同的问题。如何使这个宏接受要推断的部分类型以及完整类型?
这不是一个确切的答案,因为它不涉及宏,但请考虑使用通用函数。看起来
Build
特质可能比较合适。然后,您可以将部分推断类型与该函数一起使用,例如 graph::<StableGraph<_, _>>()
。
use petgraph::{data::Build, visit::Data};
fn graph<T>()
where
T: Build + Data + Default,
<T as Data>::NodeWeight: From<&'static str>,
<T as Data>::EdgeWeight: From<u16>,
{
let mut graph = T::default();
let a = graph.add_node("A".into());
let b = graph.add_node("B".into());
graph.add_edge(a, b, 2024u16.into());
graph
}