Skip to content
AgileLogics
5 min read

for Loops and Ranges

Prerequisites: Blocks and expressions

Ranges

@main def ranges(): Unit =
  println((1 to 5).toList)
  println((1 until 5).toList)
  println((0 to 20 by 5).toList)
  println((5 to 1 by -1).toList)
List(1, 2, 3, 4, 5)
List(1, 2, 3, 4)
List(0, 5, 10, 15, 20)
List(5, 4, 3, 2, 1)
  • 1 to 5 includes 5; 1 until 5 excludes it.
  • by sets the step.

for loops

@main def loops(): Unit =
  for i <- 1 to 3 do
    println(s"Pass $i")

  val fruits = List("apple", "banana", "cherry")
  for fruit <- fruits do
    println(s"I like $fruit")
Pass 1
Pass 2
Pass 3
I like apple
I like banana
I like cherry

for x <- collection do ... runs the body once per element. Read <- as "from" or "in".

Filters and nested loops

@main def nested(): Unit =
  for
    i <- 1 to 3
    j <- 1 to 3
    if i < j
  do
    println(s"($i, $j)")
(1, 2)
(1, 3)
(2, 3)

Several generators in one for act like nested loops; if lines filter.

for ... yield builds a collection

@main def yielding(): Unit =
  val squares = for n <- 1 to 5 yield n * n
  println(squares)

  val evens = for n <- List(1, 2, 3, 4, 5, 6) if n % 2 == 0 yield n * 10
  println(evens)
Vector(1, 4, 9, 16, 25)
List(20, 40, 60)

With yield, for is an expression that produces a new collection — no mutable list needed. This is called a for-comprehension; Level 2 shows it works with much more than collections.

With an index

@main def indexed(): Unit =
  val fruits = List("apple", "banana", "cherry")
  for (fruit, i) <- fruits.zipWithIndex do
    println(s"${i + 1}. $fruit")
1. apple
2. banana
3. cherry

Practice

Print the 5 times table from 5 x 1 = 5 to 5 x 10 = 50.

Show solution
@main def timesTable(): Unit =
  for n <- 1 to 10 do
    println(s"5 x $n = ${5 * n}")
5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50