Tags

, , , ,

The following are different ways of implementing simple loops in Scala

While loop

The Scala while loop executes a certain block of code, as long as a certain condition is true.

while(someObject.hasNext())
    process(someObject.next());
Do While Loop

The Scala  do while loop is similar to the while loop except the condition is executed after the loop body. This means that the loop body is always executed at least once.

var myInt : Int = 0; 
do { println("myInt = " + myInt); myInt+=1; } 
while(myInt < 10)
For loop

The Scala for loop also executes a certain block of code, as long as a certain condition is true. The i <- construct is called a generator. For each iteration it initializes the val i with a value.

for(i <- 1 to 10) println("i is " + i);
Omitting For

The 1 to 10 in the for loop is the Range type. To support Domain Specific Languages (DSL) the 1 to 10 is actually a method call that returns the Range type.

(1).to(10);
to vs. until

Keywords to and until can be used when creating a Range object. Inclusive to includes the last value in the range, and exclusive until leaves it out.

for(i <- 1 to 10) {
    println("i is " + i);  // prints 1-10
}

for(i <- 1 until 10) {
    println("i is " + i);  // prints 1-9
}

Tail Recursive loop

All of the above loop examples are imperative functions making use of iteration.  Scala as a functional programming language supports Recursion (tail in this example) and Iteration (as above). Because Recursion will fail if there is a finite call stack, Java, for example, prefers Iteration which holds the local variables called by the function. As a result Java provides for loops, for-each loops, while loops, do loops, arrays, Iterators, ResultSets, etc.

Scala supports Tail Recursion that can use the same stack frame by encapsulating the loop. Once the loop has completed Scala does not need the local variables anymore because it has completed all the encapsulated computations.  Scala can then reuse the exact same stack frame the next time it loops through the very same function. This limits Out of Memory exceptions and makes parallel processing easier.

def loopTailRecursive(iterator: Int, con: (Int) 
                      => Boolean, acc: List[Int]): List[Int] = {
  val suc = iterator + 1
  val temp = acc :+ suc
  if (con(suc)) loopTailRecursive(suc, con, temp) else temp
}
println(loopTailRecursive(0, (_ % 10!=0), Nil))

Scala provides the @tailrec method annotation which verifies that the method will be compiled with tail call optimisation. If it is present, the compiler will issue an error if the method cannot be optimised into a loop.