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
- For comprehension vs imperative loops: For comprehensions are more functional but may have performance overhead
- Tail recursion optimization: Use
@tailrecannotation to ensure tail recursion optimization - Avoid nested loops: Consider functional methods like
flatMap - Use View: For large collections, use
viewfor 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.