while / do-while
In Zig, the while loop repeats a block as long as a condition is true. Zig's while, break, and continue can return values as expressions, allowing flexible patterns such as producing a value when breaking out of a loop. This page covers the basic syntax of condition-based loops through to using break and continue as expressions.
Syntax
// -----------------------------------------------
// while — repeats the loop while the condition is true
// -----------------------------------------------
while (condition) {
// this block repeats while condition is true
}
// -----------------------------------------------
// while + continue expression — specifies an expression to run after each iteration
// -----------------------------------------------
while (condition) : (continue_expr) {
// continue_expr is evaluated after the loop body and before the next condition check
// equivalent to the post part of C's for (init; cond; post)
}
// -----------------------------------------------
// break — exits the loop immediately
// -----------------------------------------------
while (condition) {
if (exit_condition) break; // stops the loop
}
// -----------------------------------------------
// continue — skips the rest of the body and moves to the next iteration
// -----------------------------------------------
while (condition) : (i += 1) {
if (skip_condition) continue; // runs the continue expression, then checks the condition again
// this line is not reached when skip_condition is true
}
// -----------------------------------------------
// while as an expression that returns a value — pass a value to break
// -----------------------------------------------
const result = while (condition) : (continue_expr) {
if (return_condition) break return_value; // becomes the "return value" of the loop
} else default_value;
// the else clause is evaluated when the loop ends naturally (condition became false without a break)
Syntax Reference
| Syntax / Keyword | Description |
|---|---|
while (cond) { } | Repeats the block while cond is true. |
while (cond) : (expr) { } | Evaluates expr (the continue expression) after each iteration, before checking the condition again. |
break | Exits the current loop immediately. |
break value | Exits the loop and returns value as the result of the loop expression. |
continue | Skips the rest of the block, runs the continue expression, then moves to the next iteration. |
while (cond) { } else { } | Evaluates the else clause when the loop ends because the condition became false (not via break). |
while (cond) : (expr) { } else value | When used as an expression, the else clause provides the value when the loop ends naturally. |
Sample Code
psycho_pass_while.zig
// psycho_pass_while.zig — sample demonstrating Zig's while loop
// Uses characters from PSYCHO-PASS to show
// basic while, continue expression, break, and loop value return
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
// -----------------------------------------------
// 1. Basic while loop
// Prints the names of Division 1 enforcers in order
// -----------------------------------------------
try stdout.print("=== Division 1 Enforcer List ===\n", .{});
// Define enforcer names in an array
const enforcers = [_][]const u8{
"Kogami Shinya",
"Masaoka Tomomi",
"Kunizuka Shusei",
"Hourai Akane",
"Muki Rokujou",
};
// Iterate over the array using a while loop with an index
var i: usize = 0;
while (i < enforcers.len) {
try stdout.print(" [{d}] {s}\n", .{ i + 1, enforcers[i] });
i += 1; // must increment manually each time
}
try stdout.print("\n", .{});
// -----------------------------------------------
// 2. while loop with continue expression (: (expr))
// Writing the increment in the continue expression resembles a for loop
// -----------------------------------------------
try stdout.print("=== Inspector List (continue expression) ===\n", .{});
const inspectors = [_][]const u8{
"Tsunemori Akane",
"Ginoza Nobuchika",
"Hinakawa Shou",
"Shimotsuki Mika",
};
var j: usize = 0;
// j += 1 runs automatically after each block, including after continue
while (j < inspectors.len) : (j += 1) {
try stdout.print(" Inspector: {s}\n", .{inspectors[j]});
}
try stdout.print("\n", .{});
// -----------------------------------------------
// 3. Skipping with the continue keyword
// Only prints enforcers whose Psycho-Pass coefficient is above a threshold
// -----------------------------------------------
try stdout.print("=== Psycho-Pass Coefficient Filter (continue) ===\n", .{});
// Holds names and coefficients in parallel arrays
const names = [_][]const u8{
"Kogami Shinya",
"Masaoka Tomomi",
"Kunizuka Shusei",
"Criminally Asymptomatic",
"Muki Rokujou",
};
const coefficients = [_]u32{ 150, 180, 140, 40, 120 };
var k: usize = 0;
while (k < names.len) : (k += 1) {
// Skip anyone with a coefficient below 50 (criminally asymptomatic)
if (coefficients[k] < 50) continue;
try stdout.print(
" {s} — coefficient: {d}\n",
.{ names[k], coefficients[k] },
);
}
try stdout.print("\n", .{});
// -----------------------------------------------
// 4. Exiting the loop with break
// Stops when the first enforcer with a coefficient over 160 is found
// -----------------------------------------------
try stdout.print("=== Search for High-Coefficient Enforcer (break) ===\n", .{});
const targets = [_][]const u8{
"Muki Rokujou",
"Kunizuka Shusei",
"Masaoka Tomomi",
"Kogami Shinya",
};
const target_coeff = [_]u32{ 120, 140, 180, 150 };
var m: usize = 0;
while (m < targets.len) : (m += 1) {
try stdout.print(" Checking: {s} ({d})\n", .{ targets[m], target_coeff[m] });
if (target_coeff[m] > 160) {
try stdout.print(" → High coefficient detected: {s}\n", .{targets[m]});
break; // exit the loop after finding the first match
}
}
try stdout.print("\n", .{});
// -----------------------------------------------
// 5. Returning a value from a while expression (break value / else value)
// Gets the step count at which Tsunemori Akane's coefficient exceeds the threshold
// -----------------------------------------------
try stdout.print("=== Loop Expression Value Return (break value / else) ===\n", .{});
// Simulated list of coefficient changes
const akane_coefficients = [_]u32{ 28, 31, 35, 41, 50, 68, 89 };
const threshold: u32 = 60;
var n: usize = 0;
// The entire while expression holds a value
// The value passed to break becomes the result of the loop expression
// If the loop ends without exceeding the threshold, the else clause returns null (not found)
const exceeded_at: ?usize = while (n < akane_coefficients.len) : (n += 1) {
if (akane_coefficients[n] >= threshold) {
break n; // returns index n as the value of the loop expression
}
} else null;
if (exceeded_at) |idx| {
try stdout.print(
" Tsunemori Akane's coefficient exceeded threshold {d} at step {d} (coefficient: {d})\n",
.{ threshold, idx, akane_coefficients[idx] },
);
} else {
try stdout.print(" No step found where the threshold was exceeded\n", .{});
}
try stdout.print("\nDone\n", .{});
}
zig run psycho_pass_while.zig === Division 1 Enforcer List === [1] Kogami Shinya [2] Masaoka Tomomi [3] Kunizuka Shusei [4] Hourai Akane [5] Muki Rokujou === Inspector List (continue expression) === Inspector: Tsunemori Akane Inspector: Ginoza Nobuchika Inspector: Hinakawa Shou Inspector: Shimotsuki Mika === Psycho-Pass Coefficient Filter (continue) === Kogami Shinya — coefficient: 150 Masaoka Tomomi — coefficient: 180 Kunizuka Shusei — coefficient: 140 Muki Rokujou — coefficient: 120 === Search for High-Coefficient Enforcer (break) === Checking: Muki Rokujou (120) Checking: Kunizuka Shusei (140) Checking: Masaoka Tomomi (180) → High coefficient detected: Masaoka Tomomi === Loop Expression Value Return (break value / else) === Tsunemori Akane's coefficient exceeded threshold 60 at step 5 (coefficient: 68) Done
Overview
Zig's while loop is a straightforward construct that repeats a block as long as a condition is true. The while (cond) : (expr) { } form always runs expr (the continue expression) after the block ends, making it safe to write counter increments and similar logic. This form is equivalent to the post part of a C for statement.
break exits the loop immediately, while continue skips the rest of the body, runs the continue expression, and then moves to the next iteration. A distinctive feature of Zig is that while can be used as an expression: break value returns a result from the loop. If the condition becomes false and the loop ends naturally, the else clause provides the value — making it possible to express "found value / default if not found" in a single statement. Combined with optional types (?T), this allows search-style logic to be written concisely. See also for loop and if / switch.
If you find any errors or copyright issues, please contact us.