Initialize arrays at comptime

I try to use comptime to initialise some arrays, roughly:

const width = [_]u8{42, 24};
const height = [_]u8{1, 2};
const sizeBits: [2]u8 = undefined;
const spareBits: [2]u8 = undefined;

comptime {
    for (width, height, 0..) |w, h, i| {
        sizeBits[i] = w * h;
        spareBits[i] = (w * h) % 8;
        //...a couple other arrays to calculate at comptime.
    }
}

I somehow thought comptime would allow the setting of an undefined const. Something like a static initializer, But:

cannot assign to constant

When using vars I get: unable to evaluate comptime expression and operation is runtime due to this operand, which I think is pointing to the array index.

For sure I can just use a regular fn init() block, but this feels like a perfect use-case for comptime? What am I missing please.

const myarr = blk: {
  var myarr: [1]u8 = undefined;
  myarr[0] = 1;
  break :blk myarr;
};
1 Like

I’d do something like this:

const width = [_]u8{ 42, 24 };
const height = [_]u8{ 1, 2 };
const sizeBits: [2]u8 = init: {
    var result: [2]u8 = undefined;
    for (width, height, 0..) |w, h, i| {
        result[i] = w * h;
    }
    break :init result;
};
const spareBits: [2]u8 = init: {
    var result: [2]u8 = undefined;
    for (width, height, 0..) |w, h, i| {
        result[i] = (w * h) % 8;
    }
    break :init result;
};

test "sparebits" {
    for (spareBits, sizeBits) |spare, size| {
        std.debug.print("spare = {}, size = {}\n", .{ spare, size });
    }
}
2 Likes

Consider using tuple destructuring to avoid repeating the loop:

const sizeBits, const spareBits = init: {
    var sizes: [2]u8 = undefined;
    var spares: [2]u8 = undefined;
    for (width, height, 0..) |w, h, i| {
        sizes[i] = w * h;
        spares[i] = (w * h) % 8;
    }
    break :init .{ sizes, spares };
};
5 Likes

once it starts to get complicated, I prefer

fn myArr() [1]u8 {
    var r: [1]u8 = undefined;
    r[0] = 1;
    return r;
}

// If I'm not mistaken explicit comptime isn't required for something this simple.
const myarr = comptime myArr(); 

So this morning I learned about tuples, nice! multiple return values was something I was missing from my Go days :slight_smile:
I was trying to avoid the messy block syntax with the dodgy goto :wink: But in this case it ticks the boxes, comptime, single loop and still maintains const. Thanks!

Edit: I should have tested first… Is this syntax a new feature? Since I get expected ';' after declaration after const sizeBits,

Thanks to everyone else for their input.

1 Like