modify! — Mutation
modify! applies transactional changes to an existing graph — adding nodes, removing nodes, adding/removing edges, and swapping values — all atomically. It returns a Modification describing everything that changed.
DSL Primitives
| Symbol | Meaning |
|---|---|
N(id) | New node (local id for back-references within this modification) |
N_() | New node (auto-assigned local id) |
n(id) | Reference to new node defined earlier in same modify! |
X(id) | Existing graph node (by graph node id) |
x(id) | Reference to existing graph node (no value change) |
!X(id) | Remove existing node (and all its edges) |
E() | New edge constructor |
e() | Existing edge reference (for value swap) |
!e() | Remove existing edge |
.val(v) | Set value on node or edge |
E().include(p) | Add a part to a composite link, creating the link on a vacant pair |
E().exclude::<T>() | Drop a composite link’s T part |
E().exclude_kind(k) | Drop the part of a runtime kind |
Adding Nodes and Edges
use grw::graph::{self, MGraph, edge};
let mut g: MGraph<(), edge::Undir<()>> = MGraph::default();
// add two connected nodes
modify!(g, [N(1) ^ N(2)]).unwrap();
assert_eq!(g.node_count(), 2);
assert_eq!(g.edge_count(), 1);
// connect new node to existing
modify!(g, [X(0) ^ N(3)]).unwrap();
assert_eq!(g.node_count(), 3);
assert_eq!(g.edge_count(), 2);
let mut g: MGraph<(), edge::Dir<()>> = MGraph::default();
// directed path
modify!(g, [N(1) >> (N(2) >> N(3))]).unwrap();
assert_eq!(g.node_count(), 3);
assert_eq!(g.edge_count(), 2);
let mut g: MGraph<(), edge::Undir<()>> = MGraph::default();
// triangle via back-reference
modify!(g, [N(1) ^ (N(2) ^ (N(3) ^ n(1)))]).unwrap();
assert_eq!(g.node_count(), 3);
assert_eq!(g.edge_count(), 3);
With Values
let mut g: MGraph<&str, edge::Undir<u32>> = MGraph::default();
// node and edge values
modify!(g, [
N(1).val("a") & E().val(42u32) ^ N(2).val("b")
]).unwrap();
assert_eq!(g.node_count(), 2);
assert_eq!(g.edge_count(), 1);
// isolated node
modify!(g, [N(3).val("c")]).unwrap();
assert_eq!(g.node_count(), 3);
Removing Nodes and Edges
let mut g: MGraph<(), edge::Undir<()>> = MGraph::default();
modify!(g, [N(1) ^ N(2) ^ N(3)]).unwrap();
// remove node 1 (and its edges)
modify!(g, [!X(1)]).unwrap();
assert_eq!(g.node_count(), 2);
let mut g: MGraph<(), edge::Dir<()>> = MGraph::default();
modify!(g, [N(1) >> N(2)]).unwrap();
// remove edge, keep both nodes
modify!(g, [X(0) & !e() >> x(1)]).unwrap();
assert_eq!(g.node_count(), 2);
assert_eq!(g.edge_count(), 0);
Updating Values
A node value changes only through modify! — there is no get_mut for one —
because the swap must release the value’s old index keys and claim its new
ones, and adjust the degree tables, in the same transaction.
let mut g: MGraph<&str, edge::Undir<()>> = MGraph::default();
modify!(g, [N(1).val("old")]).unwrap();
assert_eq!(g.get(0), Some(&"old"));
// swap node value
modify!(g, [X(0).val("new")]).unwrap();
assert_eq!(g.get(0), Some(&"new"));
let mut g: MGraph<(), edge::Undir<u32>> = MGraph::default();
modify!(g, [N(1) & E().val(100u32) ^ N(2)]).unwrap();
// swap edge value
modify!(g, [X(0) & e().val(200u32) ^ X(1)]).unwrap();
Parts of a Composite Link
On a graph whose edge value is a composite, a link changes part by part:
E().include(p), E().exclude::<T>() and E().exclude_kind(k), while !e()
still deletes the whole link. The combinator decides what a link with no parts
left means — TypeSet removes it. Refusals are typed (PartRejected,
PartNotHeld, PartConflict). See Composite Values.
Modification Result
The returned Modification struct contains:
new_node_ids— mapping from local ids to real graph idsadded_edges— edges that were createdremoved_nodes/removed_edges— what was deletedswapped_node_vals/swapped_edge_vals— old values that were replaced
let mut g: MGraph<(), edge::Undir<()>> = MGraph::default();
let result = modify!(g, [N(1) ^ N(2)]).unwrap();
// the local id 1 was assigned a real graph node id
let real_id = result.new_node_ids[&LocalId(1)];
Color Legend for Diagrams
Throughout this documentation:
- Blue — added or changed elements
- Red dashed — removed elements
- Black — existing, unchanged elements