How to create your own control structures in Scala

This is an excerpt from the 1st Edition of the Scala Cookbook (partially modified for the internet). This is Recipe 3.18, “How to create your own control structures in Scala.”

Problem

You want to define your own control structures to improve the Scala language, simplify your own code, or create a DSL for others to use.

Solution

The creators of the Scala language made a conscious decision not to implement some keywords in Scala, and instead implemented functionality through Scala libraries. This was demonstrated in Recipe 3.5, “Implementing break and continue”, which showed that although the Scala language doesn’t have break and continue keywords, you can achieve the same functionality through library methods.

As a simple example of creating what appears to be a control structure, imagine for a moment that for some reason you don’t like the while loop and want to create your own whilst loop, which you can use like this:

package foo

import com.alvinalexander.controls.Whilst._

object WhilstDemo extends App {
    var i = 0
    whilst (i < 5) {
        println(i)
        i += 1
    }
}

To create your own whilst control structure, define a function named whilst that takes two parameter lists. The first parameter list handles the test condition — in this case, i < 5 — and the second parameter list is the block of code the user wants to run.

You could implement this as a method that’s just a wrapper around the while operator:

// 1st attempt
def whilst(testCondition: => Boolean)(codeBlock: => Unit) {
    while (testCondition) {
        codeBlock
    }
}

But a more interesting approach is to implement the whilst method without calling while. This is shown in a complete object here:

package com.alvinalexander.controls

import scala.annotation.tailrec

object Whilst {
    // 2nd attempt
    @tailrec
    def whilst(testCondition: => Boolean)(codeBlock: => Unit) {
        if (testCondition) {
            codeBlock
            whilst(testCondition)(codeBlock)
        }
    }
}

In this code, the testCondition is evaluated once, and if the condition is true, the codeBlock is executed, and then whilst is called recursively. This approach lets you keep checking the condition without needing a while or for loop.

Discussion

In the second whilst example, I used a recursive call to keep the loop running, but in a simpler example, you don’t need recursion. For example, assume you want a control structure that takes two test conditions, and if both evaluate to true, you’ll run a block of code that’s supplied. An expression using that control structure might look like this:

doubleif(age > 18)(numAccidents == 0) { println("Discount!") }

In this case, define a function that takes three parameter lists:

// two 'if' condition tests
def doubleif(test1: => Boolean)(test2: => Boolean)(codeBlock: => Unit) {
    if (test1 && test2) {
        codeBlock
    }
}

Because doubleif only needs to perform one test and doesn’t need to loop indefinitely, there’s no need for a recursive call in its method body. It simply checks the two test conditions, and if they evaluate to true, the codeBlock is executed.

See Also

  • One of my favorite uses of this technique is shown in the book, Beginning Scala (Apress), by David Pollak. I describe how it works on my website.
  • The Scala Breaks class is demonstrated in Recipe 3.5. Its source code is simple, and provides another example of how to implement a control structure.