Skip to content

Scala Loops

Scala provides various loop structures, including for loops, while loops, and more. Scala's loops have functional programming characteristics, supporting generators, filters, and comprehensions.

For Loops

Basic For Loop

scala
object BasicForLoop {
  def main(args: Array[String]): Unit = {
    // Basic range loop
    println("Basic for loop:")
    for (i <- 1 to 5) {
      println(s"i = $i")
    }
    
    println("\nuntil loop (excludes end value):")
    for (i <- 1 until 5) {
      println(s"i = $i")
    }
    
    println("\nStep loop:")
    for (i <- 1 to 10 by 2) {
      println(s"i = $i")
    }
    
    println("\nReverse loop:")
    for (i <- 10 to 1 by -1) {
      println(s"i = $i")
    }
  }
}

Iterating Over Collections

scala
object CollectionIteration {
  def main(args: Array[String]): Unit = {
    val fruits = List("apple", "banana", "orange", "grape")
    val numbers = Array(1, 2, 3, 4, 5)
    
    println("Iterating over list:")
    for (fruit <- fruits) {
      println(s"Fruit: $fruit")
    }
    
    println("\nIterating over array:")
    for (num <- numbers) {
      println(s"Number: $num")
    }
    
    println("\nIterating with index:")
    for ((fruit, index) <- fruits.zipWithIndex) {
      println(s"Number ${index + 1} fruit: $fruit")
    }
    
    println("\nUsing indices:")
    for (i <- fruits.indices) {
      println(s"Index $i: ${fruits(i)}")
    }
  }
}

Nested For Loops

scala
object NestedForLoop {
  def main(args: Array[String]): Unit = {
    println("Nested for loop - Multiplication table:")
    for (i <- 1 to 3) {
      for (j <- 1 to 3) {
        print(s"${i * j}\t")
      }
      println()
    }
    
    println("\nNested loop using semicolons:")
    for (i <- 1 to 3; j <- 1 to 3) {
      println(s"($i, $j) = ${i * j}")
    }
    
    println("\nThree-level nesting:")
    for {
      x <- 1 to 2
      y <- 1 to 2
      z <- 1 to 2
    } {
      println(s"($x, $y, $z)")
    }
  }
}

For Loop with Conditions

scala
object ConditionalForLoop {
  def main(args: Array[String]): Unit = {
    val numbers = 1 to 20
    
    println("Even numbers:")
    for (num <- numbers if num % 2 == 0) {
      println(num)
    }
    
    println("\nNumbers divisible by 3:")
    for (num <- numbers if num % 3 == 0) {
      println(num)
    }
    
    println("\nMultiple conditions:")
    for {
      num <- numbers
      if num % 2 == 0
      if num > 10
    } {
      println(s"Greater than 10 even number: $num")
    }
    
    println("\nString filtering:")
    val words = List("hello", "world", "scala", "programming", "fun")
    for (word <- words if word.length > 4) {
      println(s"Long word: $word")
    }
  }
}

For Comprehension

scala
object ForComprehension {
  def main(args: Array[String]): Unit = {
    val numbers = 1 to 10
    
    // Generate new collection
    val squares = for (num <- numbers) yield num * num
    println(s"Square numbers: $squares")
    
    val evenSquares = for {
      num <- numbers
      if num % 2 == 0
    } yield num * num
    println(s"Even squares: $evenSquares")
    
    // String processing
    val words = List("hello", "world", "scala")
    val upperWords = for (word <- words) yield word.toUpperCase
    println(s"Uppercase words: $upperWords")
    
    // Complex comprehension
    val coordinates = for {
      x <- 1 to 3
      y <- 1 to 3
      if x != y
    } yield (x, y)
    println(s"Coordinate pairs (x != y): $coordinates")
    
    // Nested collection processing
    val matrix = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
    val flattenedDoubled = for {
      row <- matrix
      element <- row
    } yield element * 2
    println(s"Flattened and doubled: $flattenedDoubled")
  }
}

While Loops

Basic While Loop

scala
object BasicWhileLoop {
  def main(args: Array[String]): Unit = {
    var i = 1
    
    println("While loop:")
    while (i <= 5) {
      println(s"i = $i")
      i += 1
    }
    
    // Calculate factorial
    var n = 5
    var factorial = 1
    var counter = 1
    
    while (counter <= n) {
      factorial *= counter
      counter += 1
    }
    println(s"$n! = $factorial")
  }
}

Do-While Loop

scala
object DoWhileLoop {
  def main(args: Array[String]): Unit = {
    var i = 1
    
    println("Do-while loop:")
    do {
      println(s"i = $i")
      i += 1
    } while (i <= 5)
    
    // Example that executes at least once
    var input = 0
    do {
      println("Please enter a positive number:")
      input = scala.io.StdIn.readInt()
      if (input <= 0) {
        println("Invalid input, please try again!")
      }
    } while (input <= 0)
    
    println(s"You entered positive number: $input")
  }
}

Loop Control

Break and Continue (using Breaks)

scala
import scala.util.control.Breaks._

object LoopControl {
  def main(args: Array[String]): Unit = {
    println("Using break:")
    breakable {
      for (i <- 1 to 10) {
        if (i == 6) break()
        println(s"i = $i")
      }
    }
    
    println("\nUsing continue (skip even numbers):")
    for (i <- 1 to 10) {
      breakable {
        if (i % 2 == 0) break()  // Equivalent to continue
        println(s"Odd number: $i")
      }
    }
    
    println("\nBreak in nested loops:")
    breakable {
      for (i <- 1 to 5) {
        for (j <- 1 to 5) {
          if (i * j > 10) break()
          println(s"$i * $j = ${i * j}")
        }
      }
    }
  }
}

Labeled Break

scala
import scala.util.control.Breaks._

object LabeledBreak {
  def main(args: Array[String]): Unit = {
    println("Labeled break:")
    
    outer: breakable {
      for (i <- 1 to 5) {
        inner: breakable {
          for (j <- 1 to 5) {
            if (i == 3 && j == 3) {
              println(s"Breaking outer loop at ($i, $j)")
              break(outer)
            }
            println(s"($i, $j)")
          }
        }
      }
    }
    
    println("Outer loop ended")
  }
}

Functional Loop Alternatives

Using Higher-Order Functions

scala
object FunctionalLoops {
  def main(args: Array[String]): Unit = {
    val numbers = List(1, 2, 3, 4, 5)
    
    println("Using foreach:")
    numbers.foreach(num => println(s"Number: $num"))
    
    println("\nUsing map:")
    val doubled = numbers.map(_ * 2)
    println(s"Doubled: $doubled")
    
    println("\nUsing filter:")
    val evens = numbers.filter(_ > 2)
    println(s"Evens: $evens")
    
    println("\nUsing reduce:")
    val sum = numbers.reduce(_ + _)
    println(s"Sum: $sum")
    
    println("\nUsing fold:")
    val product = numbers.fold(1)(_ * _)
    println(s"Product: $product")
    
    println("\nUsing zipWithIndex:")
    numbers.zipWithIndex.foreach { case (value, index) =>
      println(s"Index $index: $value")
    }
  }
}

Recursion as Loop Alternative

scala
object RecursiveLoops {
  // Recursive factorial
  def factorial(n: Int): Int = {
    if (n <= 1) 1
    else n * factorial(n - 1)
  }
  
  // Tail recursive factorial
  def factorialTailRec(n: Int): Int = {
    @annotation.tailrec
    def loop(n: Int, acc: Int): Int = {
      if (n <= 1) acc
      else loop(n - 1, n * acc)
    }
    loop(n, 1)
  }
  
  // Recursive list traversal
  def printList[T](list: List[T]): Unit = list match {
    case Nil => println("List end")
    case head :: tail =>
      println(s"Element: $head")
      printList(tail)
  }
  
  // Recursive Fibonacci sequence
  def fibonacci(n: Int): Int = {
    if (n <= 1) n
    else fibonacci(n - 1) + fibonacci(n - 2)
  }
  
  // Tail recursive Fibonacci
  def fibonacciTailRec(n: Int): Int = {
    @annotation.tailrec
    def loop(n: Int, prev: Int, curr: Int): Int = {
      if (n == 0) prev
      else loop(n - 1, curr, prev + curr)
    }
    loop(n, 0, 1)
  }
  
  def main(args: Array[String]): Unit = {
    println(s"5! = ${factorial(5)}")
    println(s"5! (tail recursive) = ${factorialTailRec(5)}")
    
    val list = List(1, 2, 3, 4, 5)
    printList(list)
    
    println(s"Fibonacci number at position 10: ${fibonacci(10)}")
    println(s"Fibonacci number at position 10 (tail recursive): ${fibonacciTailRec(10)}")
  }
}

Practical Examples

Number Guessing Game

scala
import scala.util.Random
import scala.io.StdIn

object NumberGuessingGame {
  def main(args: Array[String]): Unit = {
    val random = new Random()
    val targetNumber = random.nextInt(100) + 1
    var attempts = 0
    var guessed = false
    
    println("Welcome to the number guessing game!")
    println("I'm thinking of a number between 1 and 100, can you guess it?")
    
    while (!guessed && attempts < 10) {
      print("Please enter your guess: ")
      val guess = StdIn.readInt()
      attempts += 1
      
      if (guess == targetNumber) {
        println(s"Congratulations! You guessed it correctly on attempt $attempts!")
        guessed = true
      } else if (guess < targetNumber) {
        println("Too low!")
      } else {
        println("Too high!")
      }
      
      if (!guessed && attempts < 10) {
        println(s"You have ${10 - attempts} more chances")
      }
    }
    
    if (!guessed) {
      println(s"Game over! The correct answer was $targetNumber")
    }
  }
}

Matrix Operations

scala
object MatrixOperations {
  def printMatrix(matrix: Array[Array[Int]]): Unit = {
    for (row <- matrix) {
      for (element <- row) {
        print(s"$element\t")
      }
      println()
    }
  }
  
  def createMatrix(rows: Int, cols: Int): Array[Array[Int]] = {
    val matrix = Array.ofDim[Int](rows, cols)
    var counter = 1
    
    for (i <- matrix.indices) {
      for (j <- matrix(i).indices) {
        matrix(i)(j) = counter
        counter += 1
      }
    }
    matrix
  }
  
  def transposeMatrix(matrix: Array[Array[Int]]): Array[Array[Int]] = {
    val rows = matrix.length
    val cols = matrix(0).length
    val transposed = Array.ofDim[Int](cols, rows)
    
    for (i <- matrix.indices; j <- matrix(i).indices) {
      transposed(j)(i) = matrix(i)(j)
    }
    transposed
  }
  
  def main(args: Array[String]): Unit = {
    println("Creating 3x4 matrix:")
    val matrix = createMatrix(3, 4)
    printMatrix(matrix)
    
    println("\nTransposed matrix:")
    val transposed = transposeMatrix(matrix)
    printMatrix(transposed)
  }
}

Prime Number Generator

scala
object PrimeGenerator {
  def isPrime(n: Int): Boolean = {
    if (n < 2) return false
    if (n == 2) return true
    if (n % 2 == 0) return false
    
    var i = 3
    while (i * i <= n) {
      if (n % i == 0) return false
      i += 2
    }
    true
  }
  
  def generatePrimes(limit: Int): List[Int] = {
    val primes = for {
      num <- 2 to limit
      if isPrime(num)
    } yield num
    
    primes.toList
  }
  
  def sieveOfEratosthenes(limit: Int): List[Int] = {
    val isPrime = Array.fill(limit + 1)(true)
    isPrime(0) = false
    if (limit >= 1) isPrime(1) = false
    
    for (i <- 2 to math.sqrt(limit).toInt) {
      if (isPrime(i)) {
        for (j <- i * i to limit by i) {
          isPrime(j) = false
        }
      }
    }
    
    (for (i <- isPrime.indices if isPrime(i)) yield i).toList
  }
  
  def main(args: Array[String]): Unit = {
    val limit = 50
    
    println(s"Generate primes within $limit using trial division:")
    val primes1 = generatePrimes(limit)
    println(primes1.mkString(", "))
    
    println(s"\nGenerate primes within $limit using Sieve of Eratosthenes:")
    val primes2 = sieveOfEratosthenes(limit)
    println(primes2.mkString(", "))
  }
}

Performance Considerations

  1. For comprehension vs imperative loops: For comprehensions are more functional but may have performance overhead
  2. Tail recursion optimization: Use @tailrec annotation to ensure tail recursion optimization
  3. Avoid nested loops: Consider functional methods like flatMap
  4. Use View: For large collections, use view for lazy evaluation
scala
object PerformanceConsiderations {
  def main(args: Array[String]): Unit = {
    val largeRange = 1 to 1000000
    
    // Use view for lazy evaluation
    val result = largeRange.view
      .filter(_ % 2 == 0)
      .map(_ * 2)
      .take(10)
      .toList
    
    println(s"First 10 even numbers doubled: $result")
  }
}

Mastering loop structures is essential for writing efficient Scala programs, and learning to use functional programming alternatives when appropriate is also important.

Content is for learning and research only.