break, continue, and Labels
break leaves a loop.
var i: usize = 0;
while (i < 10) : (i += 1) {
if (i == 5) break;
std.debug.print("{d}\n", .{i});
}This prints:
0
1
2
3
4When i becomes 5, the loop ends.
continue skips the rest of the current iteration and starts the next one.
var i: usize = 0;
while (i < 10) : (i += 1) {
if (i % 2 == 0) continue;
std.debug.print("{d}\n", .{i});
}This prints:
1
3
5
7
9In a while loop with a continue expression, continue still runs the continue expression.
while (i < 10) : (i += 1) {
if (i < 5) continue;
std.debug.print("{d}\n", .{i});
}The update i += 1 is still performed.
A loop can have a label.
outer: while (true) {
while (true) {
break :outer;
}
}The label is written before the loop name. break :outer leaves the loop named outer, not just the inner loop.
Labels are useful with nested loops.
const table = [_][3]u8{
.{ 1, 2, 3 },
.{ 4, 5, 6 },
.{ 7, 8, 9 },
};
const target: u8 = 5;
var row: usize = 0;
var col: usize = 0;
search: for (table, 0..) |line, r| {
for (line, 0..) |value, c| {
if (value == target) {
row = r;
col = c;
break :search;
}
}
}Without the label, break would leave only the inner loop. With the label, it leaves the whole search.
continue can also use a label.
outer: for (0..3) |i| {
for (0..3) |j| {
if (j == 1) continue :outer;
std.debug.print("{d},{d}\n", .{ i, j });
}
}The output is:
0,0
1,0
2,0When j is 1, the program continues the outer loop.
A labeled break may give a value to a loop expression.
const data = [_]u8{ 3, 8, 13, 21 };
const found = search: for (data, 0..) |x, i| {
if (x == 13) break :search i;
} else null;The value of found is 2.
The label names the expression that receives the value.
The same idea works with blocks.
const x = blk: {
const a = 10;
const b = 20;
break :blk a + b;
};Here break :blk gives a value to the block.
For loops, break and else work together. The else branch runs only when the loop ends normally.
const found = for (data, 0..) |x, i| {
if (x == target) break i;
} else null;If target is found, break i gives the index. If the loop finishes without a break, the else branch gives null.
The same rule applies to while.
var i: usize = 0;
const found = while (i < data.len) : (i += 1) {
if (data[i] == target) break i;
} else null;A plain break gives no value. It is used when the loop result is not needed.
while (true) {
if (done()) break;
}A value break is used when the loop itself computes something.
const index = for (data, 0..) |x, i| {
if (x == target) break i;
} else null;Prefer plain break for control flow. Prefer value break when the loop is naturally a search, selection, or computation.
Exercise 3-21. Write a loop that stops when it finds zero.
Exercise 3-22. Write a loop that skips negative numbers and prints the rest.
Exercise 3-23. Write nested loops that search a two-dimensional array.
Exercise 3-24. Rewrite the nested search using a labeled break.