13

Multi-Object For Loops + Struct-Of-Arrays

 1 year ago
source link: https://zig.news/andrewrk/multi-object-for-loops-data-oriented-design-41ob
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Andrew Kelley

Posted on Feb 19

Multi-Object For Loops + Struct-Of-Arrays

Now that the new for loop syntax has landed, there is a pretty cool combination you can do with for loops and std.MultiArrayList:

const std = @import("std");

const S = struct {
    tag: u8,
    data: u32,
};

pub fn main() !void {
    var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    const arena = arena_instance.allocator();

    var list: std.MultiArrayList(S) = .{};

    try list.append(arena, .{ .tag = 42, .data = 99999999 });
    try list.append(arena, .{ .tag = 10, .data = 1231011 });
    try list.append(arena, .{ .tag = 69, .data = 1337 });
    try list.append(arena, .{ .tag = 1, .data = 1 });

    for (list.items(.tag), list.items(.data)) |tag, data| {
        std.debug.print("tag = {d}, data = {d}\n", .{ tag, data });
    }
}

Output:

$ zig run test.zig 
tag = 42, data = 99999999
tag = 10, data = 1231011
tag = 69, data = 1337
tag = 1, data = 1

I'll further augment it with some sorting because I think the API is pretty dang cool:

const std = @import("std");

const S = struct {
    tag: u8,
    data: u32,
};

pub fn main() !void {
    var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    const arena = arena_instance.allocator();

    var list: std.MultiArrayList(S) = .{};

    try list.append(arena, .{ .tag = 42, .data = 99999999 });
    try list.append(arena, .{ .tag = 10, .data = 1231011 });
    try list.append(arena, .{ .tag = 69, .data = 1337 });
    try list.append(arena, .{ .tag = 1, .data = 1 });

    const TagSort = struct {
        tags: []const u8,

        pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
            return ctx.tags[lhs_index] < ctx.tags[rhs_index];
        }
    };

    list.sort(TagSort{ .tags = list.items(.tag) });

    for (list.items(.tag), list.items(.data)) |tag, data| {
        std.debug.print("tag = {d}, data = {d}\n", .{ tag, data });
    }
}

Output:

$ zig run test.zig 
tag = 1, data = 1
tag = 10, data = 1231011
tag = 42, data = 99999999
tag = 69, data = 1337

The key thing to note here is that, in these examples there are two arrays, one for tag and one for data. These examples demonstrate Zig's ability to manipulate struct-of-arrays with ease.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK