Home > Articles

This chapter is from the book

12.10 Control Abstractions

In Scala, one can model a sequence of statements as a function with no parameters or return value. For example, here is a function that runs some code in a thread:

def runInThread(block: () => Unit) =
  Thread(() => block()).start()

The code is given as a function of type () => Unit. However, when you call this function, you need to supply an unsightly () =>:

runInThread { () => println("Hi"); Thread.sleep(10000); println("Bye") }

To avoid the () => in the call, use the call by name notation: Omit the (), but not the =>, in the parameter declaration and in the call to the parameter function:

def runInThread(block: => Unit) =
  Thread(() => block).start()

Then the call becomes simply

runInThread { println("Hi"); Thread.sleep(10000); println("Bye") }

This looks pretty nice. Scala programmers can build control abstractions: functions that look like language keywords. For example, we can implement a function that is used exactly as a while statement. Or, we can innovate a bit and define an until statement that works like while, but with an inverted condition:

def until(condition: => Boolean)(block: => Unit): Unit =
  if !condition then
    block
    until(condition)(block)

Here is how you use until:

var x = 10
until (x == 0) {
  x -= 1
  println(x)
}

The technical term for such a function parameter is a call-by-name parameter. Unlike a regular (or call-by-value) parameter, the parameter expression is not evaluated when the function is called. After all, we don’t want x == 0 to evaluate to false in the call to until. Instead, the expression becomes the body of a function with no parameters. That function is passed to until.

Look carefully at the until function definition. Note that it is curried: It first consumes the condition, then the block as a second parameter. Without currying, the call would look like this:

until(x == 0, { ... })

which wouldn’t be as pretty.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.