Рассматривает ли компилятор 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..].*)
        };
    }
}

Поскольку ваша ошибка возникнет на последнем проходе этой рекурсии, другим вариантом будет ее переписывание нерекурсивным способом.

Другие вопросы по тегам