Dart from the ground up

Loops: for, for in, while and do

Repeating work a counted number of times, walking through a list one value at a time, and repeating while a condition holds or until it has held once.

Part 5 of 12

Intermediate16 min readBack to Courses

The counted loop

A for loop has three parts inside its parentheses, separated by semicolons: where to start, how long to keep going, and what to do after each round. for (var i = 1; i <= 3; i++) starts at 1, keeps going while i is three or less, and adds one to i after every round.

That loop runs three times. The name i is a convention for an index, and it lives only inside the loop, so it disappears when the loop ends. i++ is shorthand for adding one, and i-- subtracts one.

Walking a list

When you already have a list, for in hands you the values one at a time without an index to keep track of: for (final name in names) { ... }. Inside the braces, name is the current value, so a loop over a price list can print each price in turn.

Use final for that variable: you are reading the value, not changing it, and the word says so to the next reader. Reach for the counted loop only when you need the position itself, such as when the index number is part of the answer.

While, and until

while repeats a block for as long as a condition is true, which suits a loop whose number of rounds you cannot count in advance. do while puts the condition after the body, so the body always runs at least once — the shape you want when the first round is what sets up the condition.

Every while loop needs a line inside it that moves the condition towards false. The variable that condition depends on is the one to watch: if nothing in the body changes it, the loop never ends and the program has to be stopped for you.

Counting from zero, and the boundary that bites

A list of three values has positions 0, 1 and 2. A loop that walks it by position starts at 0 and stops while the index is less than the length: for (var i = 0; i < names.length; i++). The < is what keeps names[3] from being asked for.

The counted loop you write for its own sake usually starts at 1, because the number is the thing being printed. The loop over a list starts at 0, because the number is an address. Mixing the two habits is where an off-by-one comes from, and the error names the position it could not find.

A loop can walk backwards too. Start at names.length - 1, keep going while the index is at least 0, and subtract one each round. Removing values while walking backwards is safer than forwards, because the positions in front of you have not shifted yet.

Leaving a loop early, and nesting one inside another

break ends the loop immediately and continues below it. continue skips the rest of the current round and goes to the next one. Both are for a loop whose normal end condition is not the whole story: stop when the answer is found, skip the rows that do not apply.

A loop inside a loop runs the inner one completely for every round of the outer one. That is how a table is built: the outer loop chooses the row, the inner loop fills its columns. The inner loop starts fresh each time, so its counter must be declared where it begins.

break leaves only the loop it sits in. Inside a nested loop it ends the inner round, not both, which is why a search that has found its value often needs a flag or a return to get out of the whole shape.

Three loops and a counter

void main() {
  for (var i = 1; i <= 3; i++) {
    print("Count " + i.toString());
  }
  final names = <String>["Ada", "Alan"];
  for (final name in names) {
    print("Hi " + name);
  }
  var left = 2;
  while (left > 0) {
    left--;
  }
  print("left: " + left.toString());
}

Four loops, one program

Run it and count the blocks in the output. Then change the counted loop to go from one to five, and make the do while run a third time by changing the number it stops at.

Output
Click "Run" to execute your code

Three loop mistakes. A condition that never becomes false, usually because the line that changes the counter sits outside the braces. Using <= with .length, which asks for one position past the end. And adding to or removing from a list while a for in loop is walking it, which changes the ground under the loop.

Try these next

  • Print a table of five rows and three columns, then change the outer bound so it prints four.
  • Use continue to skip every third number in a loop from 1 to 12.
  • Write a backwards loop that prints a three-item list in reverse without calling reversed.

A table, a skip and an early stop

Run it and look at the two blocks separately. Then change the table to six columns, and change the stopping total so the search stops one round earlier.

Output
Click "Run" to execute your code

A loop that never ends looks like a Run button that never finishes. Before you run, check that the value in the condition is really changed somewhere inside the braces.

Check what you learned

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

Part 1 of 5

What does for in hand you on each round?