I'm experimenting with n-dimensional arrays in Zig.
const expectEqual = std.testing.expectEqual;
fn NdArray(comptime n: comptime_int, comptime shape: [n]comptime_int) type {
if (shape.len == 0) {
// zero dimensional array, return the scalar type
return u8;
} else {
return struct {
// positive dimensional array, return an array of arrays one dimension lower
data: [shape[0]]NdArray(n - 1, shape[1..].*)
};
}
}
test "NdArray test" {
const expected = struct {
data: [2]struct {
data: [6]struct {
data: [9]struct {
data: u8
}
}
}
};
expectEqual(NdArray(3, [3]comptime_int{ 2, 6, 9 }), expected);
}
But I get a compile error:
11:25: error: accessing a zero length array is not allowed
data: [shape[0]]NdArray(n - 1, shape[1..].*)
^
I don't see any way for the compiler to reach line 11, when shape
has zero length. Does the compiler just forbid indexing of shape
, because it doesn't have length expressed by an integer literal?
More of an extended comment than an answer, I think as tuket
says, this seems to be compiler related. I look forward to a better explanation than the one I'm about give =D
It looks like like the struct
child scopes (if such a thing applies here) are evaluated before the outer scope. It seems to work if you shift the shape[0]
reference to the parent scope:
fn NdArray(comptime n: comptime_int, comptime shape: [n]comptime_int) type {
if (shape.len == 0) {
// zero dimensional array, return the scalar type
return u8;
} else {
var foo = shape[0];
return struct {
// positive dimensional array, return an array of arrays one dimension lower
data: [foo]NdArray(n - 1, shape[1..].*)
};
}
}
Since your error will come from the final pass of this recursion, another option would be to rewrite it in a non-recursive way.