#Succinctly defining struct of slices

1 messages · Page 1 of 1 (latest)

olive inlet
#

Hi, can someone tell me if there's a nice way to write this? optimally I'd like to define the graph in one go but it seems I have to allocate each connections_out separately and then point the slices towards them.

EDIT: See below for a better version.

pub const GraphNode = struct {
    name: []const u8,
    connections_out: []*GraphNode = &.{},
};

pub const Graph = struct {
    nodes: []GraphNode = &.{},
};

var self_nodes: [5]GraphNode = .{
    .{ .name = "start" },
    .{ .name = "GenerateVoronoiMap1" },
    .{ .name = "generate_landscape_from_image" },
    .{ .name = "beaches" },
    .{ .name = "exit" },
};

pub var self: Graph = .{};

pub fn getGraph() *const Graph {
    self_nodes[0].connections_out = &.{&self.nodes[1]};
    self_nodes[1].connections_out = &.{&self.nodes[2]};
    self_nodes[2].connections_out = &.{&self.nodes[3]};
    self_nodes[3].connections_out = &.{&self.nodes[4]};
    self_nodes[4].connections_out = &.{};
    self.nodes = self_nodes[0..];
    return &self;
}
proven wyvern
#

perhaps reconsider pointers altogether?
how about the graph be a single structure that contains all nodes, and all edges between them?
something sorta like this:

pub const Graph = struct {
    nodes: std.ArrayListUnmanaged(Node),

    pub const Node = struct {
        name: []const u8,
        connections_out: std.HashMapUnmanaged(usize, void),
    };
};
```each node contains a set of integers (`connections_out`) - those are indices into `nodes.items` of the containing `Graph`.
in this structure all of the nodes are packed together, helping cache locality; further, no pointers to nodes need ever be taken.

also note that you have a memory error in your existing code: the `&.{&self.nodes[N]}`s inside of `getGraph` are temporary variables that die at function exit; those are, however, stored inside of a global variable (`self_nodes`) - if those are later accessed you get Undefined Behaviour!
olive inlet
#

I think not using pointers is fair, but I want it to be C compatible so a hashmap sounds complicated, plus the index of the connection is important. Here's a shorter version of what I'd like to do:

pub const Graph = struct {
    pub const NodeLookup = u8;

    pub const Node = struct {
        name: []const u8,
        connections_out: []NodeLookup = &.{},
    };

    nodes: []Node,
};

pub const self: Graph = .{
    .nodes = .{
        .{ .name = "start", .connections_out = &.{1} },
        .{ .name = "GenerateVoronoiMap1", .connections_out = &.{2} },
        .{ .name = "generate_landscape_from_image", .connections_out = &.{3} },
        .{ .name = "beaches", .connections_out = &.{4} },
        .{ .name = "exit" },
    },
};