Break
A search can stop as soon as it finds what it is looking for. There is no point checking the rest of the haystack once the needle is in your hand. break leaves a loop immediately: the rest of the current pass is skipped, the condition is not tested again, and the program carries on with the first statement after the loop. It works in every loop — while, do-while, loop, and the for loop coming up later in this part.
Stopping a search early
The program looks for the smallest divisor of 91. It could try every candidate from 2 up to 90, but once one divides evenly there is no reason to keep going:
let number: int32 = 91;
var divisor: int32 = 2;
while divisor < number {
if number % divisor == 0 {
break;
}
divisor += 1;
}
2, 3, 4, 5 and 6 do not divide 91; 7 does, so the loop stops with divisor at 7 — after six candidates instead of eighty-nine.
How did the loop end?
A loop with a break can end two ways: its condition became false, or the break ran. Code after the loop often needs to know which, and it finds out by looking at the variables the loop left behind:
if divisor < number {
PrintLine("{} = {} x {}", number, divisor, number / divisor);
} else {
PrintLine("{} is prime", number);
}
flowchart LR
test{"divisor < number?"} -- "true" --> check{"number % divisor == 0?"}
check -- "yes: break" --> found["divisor < number:<br/>a divisor was found"]
check -- "no" --> step["divisor += 1"]
step --> test
test -- "false" --> prime["divisor == number:<br/>no divisor, prime"]If the loop ran out of candidates, divisor ended equal to number; if break ran, it is still below. One comparison tells the two endings apart.
break leaves one loop
With loops inside loops, break leaves only the loop it is written in — the innermost one around it. Here it ends one row of a triangle, and the outer loop carries on with the next row as if nothing happened:
var row: int32 = 1;
while row <= 4 {
var column: int32 = 1;
while column <= 4 {
if column > row {
break;
}
Print("*");
column += 1;
}
PrintLine();
row += 1;
}
Row 1 prints one star before column > row stops the inner loop, row 2 prints two, and so on. To leave an outer loop from inside an inner one, you need a label — the subject of Label.
break in a do-while
In a do-while, break also skips the test at the bottom:
var attempts: int32 = 0;
do {
attempts += 1;
if attempts == 3 {
break;
}
} while attempts < 10;
PrintLine("gave up after {} attempts", attempts);
The condition would allow ten attempts, but the break ends the loop at three.
The program
The whole lesson is one package in the Examples repository. Its comments explain every step.
// `break` leaves a loop immediately. The rest of the current pass is skipped, the condition is
// not tested again, and the program carries on with the first statement after the loop. It works
// in every loop: `while`, `do`-`while` and `loop` alike.
//
// A loop with a `break` can end two ways: its condition became false, or the `break` ran. Code
// after the loop often needs to know which, and it finds out by looking at the variables the
// loop left behind.
//
// `break` belongs inside a loop. Anywhere else it is an error:
//
// error: 'break' can only be used inside 'while', 'for', or 'loop'
import Io::{ Print, PrintLine };
func Main() -> int {
// Searching for the smallest divisor of 91. The loop could try every candidate below 91, but
// once one divides evenly there is no reason to keep going.
let number: int32 = 91;
var divisor: int32 = 2;
while divisor < number {
if number % divisor == 0 {
break;
}
divisor += 1;
}
// Reaching `number` means the condition ended the loop and no divisor was found.
if divisor < number {
PrintLine("{} = {} x {}", number, divisor, number / divisor);
} else {
PrintLine("{} is prime", number);
}
// `break` leaves only the loop it is written in. Here it ends one row of the triangle; the
// outer loop carries on with the next row as if nothing happened.
var row: int32 = 1;
while row <= 4 {
var column: int32 = 1;
while column <= 4 {
if column > row {
break;
}
Print("*");
column += 1;
}
PrintLine();
row += 1;
}
// In a `do`-`while`, `break` also skips the test at the bottom.
var attempts: int32 = 0;
do {
attempts += 1;
if attempts == 3 {
break;
}
} while attempts < 10;
PrintLine("gave up after {} attempts", attempts);
return 0;
}
Run it
cd Examples/ControlFlow/Break
rux run
91 = 7 x 13
*
**
***
****
gave up after 3 attempts
Common mistakes
break outside a loop.break belongs inside a loop. Anywhere else it fails with error: 'break' can only be used inside 'while', 'for', or 'loop'. In particular, it cannot leave an if — an if block is not a loop.break to leave every loop.In nested loops, a plain
break ends only the innermost one. The outer loop carries on. Use a label to leave an outer loop.After a search loop, the variables may describe "found" or "not found". Test them before using the result — otherwise a prime such as 97 would be reported as
97 = 97 x 1.Try it yourself
- Change
numberto97and check that the program reports it as prime. - Find the first multiple of 7 above 100 with a
loopandbreak. - Make the triangle print five rows, then make it print the triangle upside down.
Learn more
break/continuein the Rux Reference- Continue — skipping one pass instead of leaving the loop
- Label — breaking out of an outer loop