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.