Learn How To Use For Comprehension
Overview
In this tutorial, we will go over the for comprehension construct in Scala. If you are coming from another mainstream language such as Java or .NET, a for loop should be fairly self explanatory in that you are writing a piece of code to iterate over some data points.
But, the Scala for comprehension can do much more! As an example and similar to the previous tutorial on using IF And Else Expressions, the for construct in Scala can return a value!
Steps
1. A simple for loop from 1 to 5 inclusive
Let's show how to do a simple for loop by iterating from 1 to 5 and print the immutable variable numberOfDonuts during each iteration.
println("Step 1: A simple for loop from 1 to 5 inclusive")
for(numberOfDonuts <- 1 to 5){
println(s"Number of donuts to buy = $numberOfDonuts")
}
You should see the following output when you run your Scala application in IntelliJ:
Number of donuts to buy = 1
Number of donuts to buy = 2
Number of donuts to buy = 3
Number of donuts to buy = 4
Number of donuts to buy = 5
NOTE:
- We used the keyword
to
which meant that iteration number 5 was included.
2. A simple for loop from 1 to 5, where 5 is NOT inclusive
What if we wanted to iterate through numbers 1 to 4? In other words, the last iteration for number 5 will not be included. If you have used Java or .NET for loop to iterate through arrays or other collections, I'm pretty sure that at some point you must have encountered bugs in your code because you had used a <= instead of < or vice versa in your loop.
Scala's language fluency with the use of keyword until
makes it clear that your for loop will NOT include the last iteration.
println("\nStep 2: A simple for loop from 1 to 5, where 5 is NOT inclusive")
for(numberOfDonuts <- 1 until 5){
println(s"Number of donuts to buy = $numberOfDonuts")
}
You should see the following output when you run your Scala application in IntelliJ:
Number of donuts to buy = 1
Number of donuts to buy = 2
Number of donuts to buy = 3
Number of donuts to buy = 4
NOTE:
- We used of keyword
until
which meant that the iteration number 5 was NOT included.
3. Filter values using if conditions in for loop
Now that you are familiar with the for loop syntax from Step 1 and 2, let us show that in Scala you can also use if clause to add filtering support as you iterate through your items.
As an example, let's store a List of ingredients for baking donuts into an immutable variable called donutIngredients. We then loop through each ingredient in the list and filter out all items except for the "sugar" item.
println("\nStep 3: Filter values using if conditions in for loop")
val donutIngredients = List("flour", "sugar", "egg yolks", "syrup", "flavouring")
for(ingredient <- donutIngredients if ingredient == "sugar"){
println(s"Found sweetening ingredient = $ingredient")
}
You should see the following output when you run your Scala application in IntelliJ:
Found sweetening ingredient = sugar
NOTE:
- This is the first time we are showing how to declare and use a List. If you are coming from Java or .NET, you may be surprised not to find the new keyword used when declaring the List object. This is made possible in Scala using companion objects which we will see in upcoming tutorials.
- We used the if expression within the for loop itself!
- There are however better ways at filtering out items from collections which we will see in upcoming tutorials.
4. Filter values using if conditions in for loop and return the result back using the yield keyword
Let's expand the example in Step 3 and filter for either "sugar" or "syrup" ingredients in our donutsIngredients list. Instead of using the (), we are using the {} in our for comprehension to make our expressions more explicit.
In addition, to return the result of the for comprehension and store it in the sweeteningIngredients variable, we will make use of the yield
keyword.
println("\nStep 4: Filter values using if conditions in for loop and return the result back using the yield keyword")
val sweeteningIngredients = for {
ingredient <- donutIngredients
if (ingredient == "sugar" || ingredient == "syrup")
} yield ingredient
println(s"Sweetening ingredients = $sweeteningIngredients")
You should see the following output when you run your Scala application in IntelliJ:
Sweetening ingredients = List(sugar, syrup)
5. Using for comprehension to loop through 2-Dimensional array
It is very common in other programming languages to work with 2-Dimensional arrays. Let's create a 2-Dimensional array consisting of 4 elements of our donuts Ingredients.
To do this, we will use Scala Array class and call the ofDim() function, pass in the type of String in square brackets [String] and then specify our 2 by 2 array in the function parameter. We then fill in each element of our 2-Dimensional array as follows:
val twoDimensionalArray = Array.ofDim[String](2,2)
twoDimensionalArray(0)(0) = "flour"
twoDimensionalArray(0)(1) = "sugar"
twoDimensionalArray(1)(0) = "egg"
twoDimensionalArray(1)(1) = "syrup"
To iterate through your 2-Dimensional array, you can use the for comprehension and first declare an x variable to loop from 0 until 2, followed by a second iteration again from 0 until 2 which you will store in variable y. After the closing } of our for loop, you can call println() to print each element of our 2-Dimensional array.
for { x <- 0 until 2
y <- 0 until 2
} println(s"Donut ingredient at index ${(x,y)} = ${twoDimensionalArray(x)(y)}")
You should see the following output when you run your Scala application in IntelliJ:
Step 5: Using for comprehension to loop through 2-Dimensional array
Donut ingredient at index (0,0) = flour
Donut ingredient at index (0,1) = sugar
Donut ingredient at index (1,0) = egg
Donut ingredient at index (1,1) = syrup
NOTE:
- We are making use of String interpolation in our println() function.
- Learn more from our previous tutorial on Scala's String interpolation feature.
Summary
In this tutorial, we went over the following:
- How to use a for comprehension to loop and iterate from 1 to 5 inclusive
- How to use a for comprehension to loop and iterate from 1 until 5, where the fifth iteration is not included
- How to filter values using if conditions in a for loop
- How to create and use for comprehension for looping over 2-Dimensional arrays.
Tip
- As you get more familiar with functional style of programming, Scala's for comprehension will quickly become your new best friend :)
- Moreover, as we get to tutorials on say Futures, you will see even more hidden powers of the for comprehension!
Source Code
The source code is available on the allaboutscala GitHub repository.
What's Next
In the next tutorial, I will explain in more detail Scala's Range construct. As an example, our for loop in Step 1 contained a simple range which was numberOfDonuts <-1 to 5
Stay tuned!