Counting backwards
A for-in loop over a range such as 1...5 only counts up. To count down, use stride with a negative step:
for i in stride(from: 7, through: 3, by: -1) {
print(i)
}
The output is:
7
6
5
4
3
How the pieces fit
from: 7is where the sequence starts.by: -1adds -1 each time, so the value goes down by one.through: 3is the last value allowed. Because the sequence is moving downwards, it stops once the next value would be below 3, and 3 itself is included.
Swift's stride has no separate condition to write. The end value and the direction of the step are enough: the sequence continues while the value has not gone past the end in the direction of the step. With stride(from: 7, to: 3, by: -1) the end value is excluded, and the loop prints 7, 6, 5 and 4.
The direction must match the step
The sign of the step has to point from the start toward the end. If it points the other way, the sequence is empty and the loop body never runs:
for i in stride(from: 3, through: 7, by: -1) {
print(i)
}
This prints nothing, because stepping down from 3 never reaches 7. A step of 0 is not allowed and stops the program with a run-time error.
Bigger steps downwards
The step does not have to be -1. A step of -5 counts down in fives, and a step that doesn't land exactly on the end value just stops at the last value before it:
for i in stride(from: 20, through: 0, by: -5) {
print(i, terminator: " ")
}
for i in stride(from: 10, through: 1, by: -4) {
print(i, terminator: " ")
}
20 15 10 5 0 10 6 2
The first loop prints 20, 15, 10, 5 and 0. The second prints 10, 6 and 2 and stops, because the next value, -2, is below 1.
The exercise: from 5 down to -5
The task is to print every number from 5 down to -5, in decreasing order. It is built in two steps.
- Write the loop header. The start is 5, the end is -5 and the step is -1. The task includes -5, so use
through:. The variable is calledi. - Print
iin the body. Each pass prints the current value on its own line.
for i in stride(from: 5, through: -5, by: -1) {
print(i)
}
The loop prints 5, 4, 3, 2, 1, 0, -1, -2, -3, -4 and -5, which is eleven lines. The sequence crosses zero without any special handling, because stride only compares each value with the end.
Another way: reversed()
A range can also be turned around with reversed():
for i in (0...3).reversed() {
print(i, terminator: " ")
}
3 2 1 0
This works when the step is 1. For bigger steps, or when the start and end are awkward, stride is the more direct choice.
Common mistakes
- Using
to:and losing the last number.stride(from: 5, to: -5, by: -1)stops at -4. - A positive step.
by: 1from 5 to -5 gives an empty sequence, so nothing is printed. - A reversed closed range.
5...-5is not a valid range because its start is above its end, and the program crashes at run time. - Forgetting the negative sign. Writing
by: 1instead ofby: -1is the most common slip.
Key takeaways
- Count down with
strideand a negativeby:. through:includes the end value,to:excludes it.- If the step points away from the end, the loop runs zero times.
- A plain range cannot count down;
reversed()orstridecan.
