Hello, I am working on a small weighted graph struct to learn zig. I want to build an iterator over all edges. See the edgeIter
function and the related EdgeIter
struct. Something weird happen when I call the next
function of EdgeIter
. I added a few print statements to show that the lengths of the two ArrayLists are changed but I don’t understand why since graph
is a constant pointer and I am not updating it anywhere.
const std = @import("std");
const ArrayList = std.ArrayList;
pub const Graph = struct {
nodes: ArrayList(f32),
edges: ArrayList(f32),
pub fn init(allocator: std.mem.Allocator, num: usize) !Graph {
var nodes = try ArrayList(f32).initCapacity(allocator, num);
nodes.appendNTimesAssumeCapacity(0.0, num);
var edges = try ArrayList(f32).initCapacity(allocator, num * (num - 1) / 2);
edges.appendNTimesAssumeCapacity(0.0, num * (num - 1) / 2);
return .{
.nodes = nodes,
.edges = edges,
};
}
pub fn deinit(graph: Graph) void {
graph.nodes.deinit();
graph.edges.deinit();
}
pub fn numNodes(graph: Graph) usize {
return graph.nodes.items.len;
}
pub fn edgeIter(graph: Graph) EdgeIter {
return EdgeIter{ .graph = &graph, .index = 0, .first = 0, .second = 1 };
}
};
pub const Edge = struct {
first: usize,
second: usize,
value: f32,
};
pub const EdgeIter = struct {
graph: *const Graph,
index: usize,
first: usize,
second: usize,
pub fn next(self: *EdgeIter) ?Edge {
std.debug.print("\n------------\n", .{});
std.debug.print("nodes.items.len = {}\n", .{self.graph.nodes.items.len});
std.debug.print("edges.items.len = {}\n", .{self.graph.edges.items.len});
if (self.index >= self.graph.edges.items.len) {
return null;
}
const edge = Edge{
.first = self.first,
.second = self.second,
.value = self.graph.edges.items[self.index],
};
self.index += 1;
self.second += 1;
if (self.second == self.graph.numNodes()) {
self.first += 1;
self.second = self.first + 1;
}
return edge;
}
};
pub fn main() !void {
const alloc = std.heap.page_allocator;
const graph = try Graph.init(alloc, 4);
defer graph.deinit();
var iter = graph.edgeIter();
while (iter.next()) |edge| {
_ = edge;
}
}
For reference, this is the output I get
------------
nodes.items.len = 4
edges.items.len = 6
------------
nodes.items.len = 140728799473088
edges.items.len = 0
Also, if I try to print the actual items
instead of items.len
I get a segmentation fault.