Condition-controlled iteration (while loops)

Imagine you're filling a bath. You don't turn the tap on for "exactly 47 seconds" — you turn it on and keep it running while the bath isn't full yet, then stop the moment it is. You didn't count in advance; you watched a condition and repeated until it stopped being true.

That is a condition-controlled loop. In code it's written with the keyword while:

\texttt{while (condition) \{ \; do this again \; \}}

The computer checks the condition. If it's true, it runs the block inside the curly braces, then loops back and checks again. As soon as the condition is false, it skips the block and carries on with the rest of the program. So the loop keeps going until the condition becomes false — however many times that takes.

When you don't know the count in advance

You already know the count-controlled loop — the for loop — which is perfect when you know the number of repeats before you start ("do this 10 times", "for every pupil in the class"). But loads of problems aren't like that:

In every case the number of repeats depends on what happens during the loop, so you can't put a fixed count at the top. That's exactly when you reach for while.

Your first while loop: halving down to 1

Start with a number and keep halving it while it is still bigger than 1. How many halvings will that take? It depends on the number — so we let the condition n > 1 decide when to stop. Press Run and watch it count the steps.

let n: number = 64; let steps: number = 0; while (n > 1) { // keep looping WHILE n is still bigger than 1 n = Math.floor(n / 2); // progress: n gets smaller every time steps = steps + 1; console.log("after halving, n = " + n); } console.log("Reached 1 in " + steps + " steps.");

Try changing 64 to 1000, or to 7. The loop runs a different number of times each time — but you never had to work out that number yourself. The condition did it for you.

The three parts every while loop needs

Look back at that example and you'll spot the pattern that every safe while loop follows. Miss any one of the three and the loop misbehaves.

  1. Set something up before the loop — here let n = 64. The condition needs a value to test.
  2. A condition to check each time round — here n > 1. While it's true, the loop keeps going.
  3. Make progress inside the loop — here n = Math.floor(n / 2). Every pass must nudge things towards making the condition false, or the loop never ends.

That third part is the heart of it: something inside the loop must change so that the condition will eventually become false. If nothing changes, nothing ever stops.

Counting up instead: doubling past 100

A while loop doesn't have to count down. Here we start at 1 and keep doubling while we're still at or below 100. We've no idea in advance how many doublings that is — the loop finds out.

let value: number = 1; let doublings: number = 0; while (value <= 100) { // keep doubling WHILE we're not yet over 100 value = value * 2; doublings = doublings + 1; console.log(doublings + ": value is now " + value); } console.log("First value over 100 is " + value + ", after " + doublings + " doublings.");

Notice the loop overshoots: it stops at 128, the first value greater than 100, because the condition is only checked at the top of each pass. Once value becomes 128 the check 128 \le 100 is false, so the loop ends — but 128 was already stored. Checking the condition at the top is a defining feature of the while loop.

A rocket countdown

Here's a countdown written with while. We keep printing and subtracting one while the counter is still above zero.

let count: number = 5; while (count > 0) { console.log(count + "..."); count = count - 1; // step towards the stopping condition } console.log("Lift-off! 🚀");

This one could have been a for loop, because we happen to know it's 5 steps. That's the honest truth about the two loops: many problems can be written either way, and a while can always do a for's job. But when the number of repeats is genuinely unknown until you run, only a condition-controlled loop fits comfortably.

while versus for — a quick comparison

Both loops repeat; they differ in what decides the stopping.

A handy rule of thumb: if you can finish the sentence "repeat exactly ___ times" with a number, use for. If the best you can say is "repeat until ___", use while.

The classic while bug is the infinite loop: if the condition never becomes false, the loop never ends. Almost always it's because the loop forgot to make progress — nothing inside it changes the thing the condition tests. This countdown is broken because it prints forever without ever subtracting from count:

let count = 5; while (count > 0) { console.log(count); // BUG: count never changes, so count > 0 is ALWAYS true → loops forever }

In a real program an infinite loop makes the computer hang — it just sits there spinning, doing nothing useful, until you force-quit it. (In this Primer's Run boxes we cut a runaway loop off automatically after about a second, so you won't freeze your browser — but you'd get no "Lift-off", just a wall of the same number.)

The fix is always the same: make sure something inside the loop moves the condition towards false. Before you run a while loop, ask yourself: "what changes each pass, and will that eventually stop it?" Here the cure is a single line — count = count - 1; — the very line the broken version left out.

Because while checks the condition before the first pass, a loop can run zero times. If you write let n = 1; then while (n > 1) { ... }, the condition is false immediately, so the block is skipped entirely and never runs once. That's not a bug — it's often exactly what you want (a "do it only if there's anything to do" loop). It's another reason while is so flexible: it can run any number of times from zero upwards.