Tuesday, November 6, 2012

Scala Loops

Just like in Java, Scala has while and do loops. For example, you can write a while loop like this.

while (x > 0) {
    y = y + 1

However, there is no for loop like you're familiar with in Java with a structure of for (initialize; test; update). However, once you get comfortable with Scala, you'll see that the for loop in Scala is much better. Here's a for loop that loops from 1 to 10.

for (x <- 1 to 10) {

To me, the use of the to syntax is very expressive. The call 1 to 10 returns a Range of those values from 1 to 10. It's inclusive, so 10 is part of that Range. What's even cooler, is that the type of the variable x is auto-magically the same element type of the collection.

Let's say you need the range to exclude the last element. This is often the case if you're iterating over the characters in a string or array. You can do that by changing the to to until. The following code will iterate over the string "Travis" one character at a time.

val name = "Travis"
     for (x <- 0 until name.length) {

Of course, you can be even more concise in Scala and write this instead.

val name = "Travis"
    for (x <- name) {

When you look at the syntax, it makes sense, because in the context of the code, we already know that name is a string, so we'd expect "c <- name" to iterate over that string and make "c" a character type.

With every new Scala feature that I learn, I get even more excited to find the next great feature in the language that builds on the previous feature. I don't know about you, but whether I like it or not, the need for nested loops is always there. Scala gives us a really clean syntax for writing nested loops that de-clutters the code and makes it much easier to read. Take the following Java code, for example.

//Java code
for (int i=1; i < 5; i++) {
   for (int j=1; j < 5; j++)    {

In Scala, we can write this instead.

// prints 1 2 2 4 3 6 4 8
for (i <- 1 until 5; j <- 1 until 3) {
   print (i * j + " ")

These are called generators and you can have as many as you like. Each generator can have a guard, which is just a Boolean condition that follows an if.

// prints 2 2 3 6 4 8
for (i <- 1 until 5; j <- 1 until 3 if i != j) {
   print (i * j + " ")

If you need to, you can define variables inside your for loop definition and use them in the expression to evaluation the loop. For example, the following loop defines a new variable named "y" that is used inside the loop.

// prints 9 10 11 12 13 14 15 16 18 20 22 24 26 28
for (i <- 1 until 3; y = 10 - i; j <- y until 15) {
   print (i * j + " ")

If you need to build a collection of values from a loop, you can do this very concisely as well. Here's a Scala loop that constructs a collection of integer values. In Scala, we call this a for comprehension.

// Builds a Vector(2, 4, 6, 8, 10)
for (i <- 1 to 5) yield i * 2

If you haven't picked up Scala yet, I encourage you to take it for a test drive and I think you'll really like its expressiveness. It's free of clutter, easy to read, and quick to write (i.e. less code). Loops are a great example of this.

No comments:

Post a Comment