Pascal from the ground up

Three loops: for, while and repeat

A counted for loop, a while loop that checks first, and a repeat loop that checks last — and how to tell which one a piece of work wants.

Part 5 of 12

Intermediate15 min readBack to Courses

for counts for you

for i := 1 to 5 do runs the body five times, with i taking the values 1, 2, 3, 4 and 5 in turn. The start and finish are worked out once, before the first pass, and downto counts the other way.

The counter belongs to the loop. Pascal advances it after each pass, so changing it inside the body is a mistake even where the compiler allows it: the loop will still finish when it planned to.

A for loop is the right choice when the number of passes is known before the first one: a range of values, the slots of an array, the letters of a word.

Pascal evaluates the finish once, at the start, so for i := 1 to count do cannot be extended by changing count inside the body. That surprises programmers who expect the bound to be re-read on every pass. If the end really depends on the work, that is a while wearing a for costume.

while checks before every pass

while condition do tests before each pass, so a condition that is false at the start means the body never runs at all. Useful when the end depends on the work: keep halving a number until it reaches one.

Because the test is at the top, everything the condition reads has to be set up before the loop. A while whose condition never changes is an infinite loop, and the run stops on a time limit rather than an error message.

A while loop is the general form: it can express any repetition, including the counted ones, at the cost of writing the start, the test and the step yourself. The counted for exists because those three parts are easy to get wrong, and because the compiler can check them together.

repeat runs at least once

repeat ... until condition puts the test at the bottom, so the body always runs at least once. The loop stops when the condition becomes true — the opposite of while, where it continues while the condition is true.

Note the punctuation: repeat and until are keywords rather than a block, so the statements between them are separated by semicolons and there is no begin or end.

All three, one after another

program Main;
var
  i: integer;
begin
  for i := 1 to 3 do
    writeln('for ', i);
  i := 3;
  while i > 0 do
    i := i - 1;
  repeat
    i := i + 1;
  until i = 2;
  writeln('after ', i);
end.

What the loop really repeats

A for loop wraps three steps: set the counter to the start, compare it with the finish, run the body, then advance. The finish expression is evaluated once at the beginning, so changing the variable it reads inside the body does not move the finish line. Assigning to the counter is not a way to skip passes either; the loop still advances on its own schedule.

while repeats the test on every pass, which is why its condition has to read something the body changes. repeat puts the same test at the bottom, so the body runs once before the first check. A nested for runs its inner loop completely for each pass of the outer one, which is the shape behind tables and grids.

Choosing between the three

Ask what decides when the loop stops. If the answer is a fixed count — five passes, every slot of the array — use for. If the answer is a condition that the work itself changes, such as halving until the number is one, use while, because the test belongs at the top and the body may not run at all. If the work has to happen once before there is anything to test — ask, then check the answer — use repeat.

The choice is about the shape of the problem, not about speed. All three compile to the same kind of jump, and rewriting one as another is a good exercise precisely because the difference is where the test sits and which values exist when it runs.

Three loop mistakes to watch for: a semicolon straight after do, which leaves the loop body empty and runs the next statement once; a while whose body never changes the tested variable, which runs until the time limit; and a repeat whose condition is copied from a while, which stops on the opposite answer.

Try these next

  • Change the sum loop to count from 1 to 10 and predict the total before running.
  • Write a while loop that prints the odd numbers from 1 to 9, then write the same thing as a for.
  • Make the countdown start at 5 and watch the repeat loop restore the value.

Sum, count down, repeat

Run it, then change the for loop to count to 10 and predict the sum before you run it again. Then make the countdown start at 5.

Output
Click "Run" to execute your code

A line that mixes write calls inside a loop and one writeln after it is how a row of values is printed across a single line rather than one per line.

A multiplication table with nested loops

Run it, then change both loops to count to 6. Predict the last row before you run it again.

Output
Click "Run" to execute your code

Check what you learned

One question at a time. A wrong answer explains itself — take another go.

Part 1 of 5

How many times does for i := 1 to 3 do run its body?