Scala Tutorials Part #13 - Loops
Originally Posted On : 20 Mar 2017 Last Updated : 26 Aug 2018
Loops
Loops are fundamental building blocks of imperative programming languages. Since scala also supports imperative style, lets take a look at different variations of loops and how they work.
This is part 13 of the scala tutorial series. Check here for the full series.
While loops in scala are very similar to their other language counterparts, so I am not going to explain it.
The for
loop however, can be used as a drop in replacement for any while loop construct.
Index
- Concept of looping
- Introduction to the Syntax
- Controlling both indexes
- Controlling only the starting index
- No Index for expressions
- For loop with guards
- Yield construct
- Multiple Generators
Concept of looping
The concept of looping came up in early languages such as the assembly language. Several variations exist with different instruction sets.
Taken from here, a few examples below in several languages.
For loops in assembly
xor cx,cx ; cx-register is the counter, set to 0
loop1 nop ; Whatever you wanna do goes here, should not change cx
inc cx ; Increment
cmp cx,3 ; Compare cx to the limit
jle loop1 ; Loop while less or equal
Do while in C
int x=1;
do{
//Do something!
//Increment the counter so that you avoid infinite loops
x++;
}
while(x<10)
The concept is the same immaterial of the language i.e doing something repetitively.
Introduction to the Syntax
Loops in Scala do not have a three part structure like Java. A typical for loop in Java would like below,
for(int i=0;i<10;i++){
//Some code
}
A typical Scala for loop on the other hand does not have the increment part and also the variable declaration is slightly different.
for(i <- 1 to 10){
println(i)
}
Scala does not really have anything that is similar to Java for loops. If you take a closer look, the to
is actually a method on the RictInt
class which gives back a Range
collection from 1 to 10. But notice that we are using these directly from the Int
class. This is because the class RichInt
is not a normal class but something called a booster class. We will take a look at booster classes in later tutorials. For now, it is sufficient to understand that the for
is not something native to Scala, but it is just syntactic sugar over iterating a Range
.
The i <- 1 to 10
part is called a loop generator. In below sections we will see how we can combine multiple generators to create a nested for loop.
Controlling both indexes
In any for loop, there are two indexes involved i.e the beginning index and the ending one. We can use different constructs if we want to control either of these indexes.
val array = Array(10,12,23,44)
for(i<-0 to array.length-1){
println(array(i))
}
Starting from i = 0
we loop till array length -1. As in many languages, arrays are indexed from 0. In this style of writing, we need to be careful in both the
beginning and end index. Typically one would make mistakes by starting at index 0 and then ending at array.length
which would cause ArrayIndexOutOfBoundsException
.
Controlling only the starting index
If we are worried about only the starting index then scala has a special construct for that.
for(i<-0 until array.length) {
println(array(i))
}
The until
keyword makes sure that the loop iterates until the last element without us having to deal with the end index. Similar to to
, until
is also a method in the RichInt
class.
No Index for expressions
In java there are Iterators
in which you can loop through arrays without worrying about indexes and there are for loops in which we need not worry
about the indexes.
int a[] = {10,12,23,44};
for(int i:a){
System.out.println(i);
}
The scala version of the above would be quite similar,
for(i<- array) {
println(i)
}
There are reasons about why one would use any of the above. In the no index version there is no control over where the element is in the array i.e there is no track of the index. In certain situations there is no need to worry about it.
For loop with guards
Many times we want to loop over something that satisfies a condition. In java we typically do so by wrapping the for loop inside of an
if statement. In scala there is a special syntax for it and they are named as Guards
in loops. Let’s look at an example.
for(i<-0 to 30)
if (i>10 && i<30) {
println(i)
}
Notice that the if condition is wrapped inside of the for construct. We can also chain complex if conditions.
for(i<-0 to 30)
if (i>10 && i<30)
if (i%2 == 0)
if (i%4 == 0)
{
println(i)
}
This is just syntactic sugar over normal if statements.
Yield construct
For loops unlike Java generates a value in Scala. We saw this already in part 7 where is every expression is a value and every value is an object in Scala.
The variable x
is of type Unit
which is the equivalent of void in java, but as discussed before, this is actually a type.
Scala has a new keyword called yield
which produces new value out of a for loop.
val a = Array(1,2,3,4,5)
val b = for (i <- a) yield i*2
Unlike regular for loops which is of type Unit
this actually yields as the name implies another array of 5 elements.
We can even print out the array b
which will turn out to be numbers 2,4,6,8,10
.
As we get deeper into functional programming, we will find out that this way of looping leads to really good and maintainable code.
Multiple Generators
We can easily create nested for loops with generator syntax.
for(i <- 1 to 5;j <- 1 to 5){
println(s"i: $i j:$j")
}
This prints out
i: 1 j:1
i: 1 j:2
...
i: 5 j:5
There are more advanced constructs possible with loops, but this should be enough to get started. As we explore more into Scala, we would find that loops can be replaced with more powerful constructs which are thread safe and safer/elegant to work with.