Условия, циклы и блоки
Осваиваем поток управления: ветвления, циклы и switch без сюрпризов.
Блок в Zig — это выражение: он может возвращать значение через
break :label value, поэтому многие конструкции пишутся компактно и без временных переменных.
Управляющие конструкции Zig покажутся знакомыми любому, кто писал на C, но в каждой есть аккуратные улучшения. Главное правило: никакого скрытого поведения. switch не проваливается между ветками, if можно использовать как выражение, а циклы интегрированы с опциональными типами и ошибками.
if как выражение
const n: i32 = 7;
const sign = if (n > 0) "плюс" else if (n < 0) "минус" else "ноль";
// sign == "плюс"
Здесь if возвращает значение, как тернарный оператор в C, но без отдельного синтаксиса ? :. Условие обязано быть типа bool — целое число «как истинность» не сработает, в отличие от C.
Цикл while
var i: u32 = 0;
var sum: u32 = 0;
while (i < 5) : (i += 1) {
sum += i;
}
// sum == 0+1+2+3+4 == 10
Часть после двоеточия — выражение продолжения: оно выполняется в конце каждой итерации. Это удобно, потому что отделяет «шаг» цикла от его тела, и continue всё равно его выполнит.
Цикл for по срезам
const items = [_]u8{ 10, 20, 30 };
for (items, 0..) |value, index| {
std.debug.print("{d}: {d}\n", .{ index, value });
}
Цикл for в Zig идёт по элементам массива или среза. Захват |value| даёт текущий элемент, а добавление 0.. и второго захвата |value, index| — ещё и индекс. Это безопаснее ручного индексирования: выход за границу невозможен.
switch без проваливания
const code: u8 = 2;
const name = switch (code) {
0 => "ноль",
1, 2, 3 => "мало",
else => "много",
};
// name == "мало"
В отличие от C, ветки switch не проваливаются — не нужен break в каждой. Несколько значений объединяют запятой, диапазоны пишут как 1...9. switch обязан покрыть все случаи: либо перечислить все, либо добавить else.
Как работает под капотом
Блок с меткой возвращает значение через break :label value. Компилятор разворачивает это в обычное вычисление без накладных расходов. Поскольку switch обязан быть исчерпывающим, при добавлении нового варианта перечисления компилятор заставит вас обработать его — это ловит забытые случаи на этапе сборки.
Частые ошибки
Программисты из C пишут if (x) для ненулевого числа — Zig требует именно bool, так что нужно if (x != 0). Вторая ловушка — ожидать проваливания в switch и забыть, что в Zig его нет. Третья — неисчерпывающий switch без else: компилятор не пропустит.
Итог
if— выражение; условие обязано бытьbool, а не числом.- У
whileесть выражение продолжения после двоеточия. forидёт по элементам среза, индекс добавляют через0...switchне проваливается и обязан покрыть все случаи.