Ranges: Counting Without a List
The track coach wants to call out every lap: "Lap 1", "Lap 2", all the way to 12. There is no list of laps to loop over, only a count. A Range turns a count into something a for can walk.
The rule
toincludes the end,untilstops before it,bysets the step.
1 to 5 // 1, 2, 3, 4, 5
1 until 5 // 1, 2, 3, 4
0 to 20 by 5 // 0, 5, 10, 15, 20
10 to 1 by -3 // 10, 7, 4, 1
5 to 1 // empty: the default step is +1- A Range stores only three numbers: start, end and step.
1 to 1_000_000takes no more memory than1 to 5, because the numbers are worked out as you walk them. - It behaves like an immutable sequence:
(1 to 5).sumis 15, and(1 until 5).toListisList(1, 2, 3, 4). - To count down, give a negative step. Without one, a Range whose start is above its end is simply empty, and a loop over it silently does nothing.
Ranges pair naturally with for:
for lap <- 1 to 12 do
println(s"Lap $lap")They also pair with positions in a sequence. Positions run from 0 to length − 1, so use until, or let the collection supply them with indices:
for i <- 0 until runs.length do println(s"Run ${i + 1}: ${runs(i)} km")
for i <- runs.indices do println(runs(i)) // the same positionsThe shortcut
Think "counting laps" or "counting positions"? Things people number from 1, such as laps, weeks or runners, use 1 to n. Positions in a collection start at 0, so they use 0 until n, or indices. The word tells you which end to trust.
The collection
runshas 4 elements, at positions 0, 1, 2 and 3.
Drills
Answer fast — trust the rule.
What is (1 until 5).toList?
How many numbers are in 0 to 20 by 5?
What is (10 to 1 by -3).toList?
What does for i <- 5 to 1 do println(i) print?
runs has 4 elements. What does for i <- 0 to runs.length do println(runs(i)) do?
Remember
toincludes the end,untilstops before it, andbysets the step, negative to count down.- Laps and weeks count from 1 with
to; positions count from 0 withuntilorindices. - Trap:
0 to lengthruns off the end, and a downward range without a negative step is empty.
