Рассматривает ли компилятор Zig массивы с переменной длиной во время компиляции как возможные массивы нулевой длины?
Я экспериментирую с n-мерными массивами в 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);
}
Но я получаю ошибку компиляции:
11:25: error: accessing a zero length array is not allowed
data: [shape[0]]NdArray(n - 1, shape[1..].*)
^
Я не вижу возможности компилятору достичь строки 11, когда
shape
имеет нулевую длину. Компилятор просто запрещает индексацию
shape
, потому что у него нет длины, выраженной целочисленным литералом?
1 ответ
Я думаю, это скорее развернутый комментарий, чем ответ.
tuket
говорит, что это похоже на компилятор. Я с нетерпением жду объяснения получше, чем то, которое я собираюсь дать =D
Похоже, что
struct
дочерние области (если это применимо здесь) оцениваются до внешней области. Вроде работает, если сдвинуть
shape[0]
ссылка на родительскую область:
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..].*)
};
}
}
Поскольку ваша ошибка возникнет на последнем проходе этой рекурсии, другим вариантом будет ее переписывание нерекурсивным способом.