The ‘using’ control structure in Beginning Scala (by David Pollak)

In David Pollak's book, Beginning Scala, he introduces a using control structure that is helpful in several ways. First, it can be used to automatically close any resource that has a close method. Second, it's a great example of how to create a custom control structure in Scala.


(this space intentionally left blank because of the table of contents over there ⟶)

 

David Pollak’s “using” control structure

Here's the source code for the using control structure he created:

// required when using reflection, like `using` does
import scala.language.reflectiveCalls

/**
 * From the book, Beginning Scala, by David Pollak.
 */
object Control {

  def using[A <: { def close(): Unit }, B](param: A)(f: A => B): B =
    try {
      f(param)
    } finally {
      param.close()
    }

}

This is a clever bit of code that creates a new control construct you can use named using that we'll use to perform our inserts. If you're comfortable with the syntax shown, you can see that this construct automatically calls the close() method on the param it's given. More on this shortly.

David Pollak’s “using” control structure

A second way to demonstrate the Loan Pattern is with the using method described on the Loan Pattern website. The best implementation I’ve seen of a using method is in the book Beginning Scala (Apress), by David Pollak. Here’s a very slight modification of his code:

The using method takes two parameters:

  • An object that has a close() method
  • A block of code to be executed, which transforms the input type A to the output type B

The following code demonstrates how to use this method when reading from a file:

import Control._

object TestUsing extends App {
    using(io.Source.fromFile("example.txt")) { source => {
        for (line <- source.getLines) {
            println(line)
        }
    }}
}

Using ‘using’ with MongoDb and Casbah

That code may not make much sense on its own, so here's an example of how I used it in an application:

import com.mongodb.casbah.Imports._
import Common._
import Control._

object Insert extends App {

  // create some Stock instances
  val apple = Stock("AAPL", 600)

  // save them to the mongodb database
  saveStock(apple)

  // uses the 'using' control structure to automatically close the db connection
  def saveStock(stock: Stock) {
    using(MongoFactory.getConnection) { conn => {
       MongoFactory.getCollection(conn).save(buildMongoDbObject(stock))
     }
    }
  }
}

While I later learned that you don't need to close Casbah connections manually like this, this approach shows how to use the using method in your own code.

How the ‘saveStock’ method works

The saveStock method takes advantage of the using control structure and my MongoFactory (not shown). This code does the following:

  • Gets a MongoConnection from the MongoFactory.
  • Calls the save method on the MongoCollection instance.
  • Automatically closes the MongoConnection, courtesy of the using control structure.

How the using control structure works

Let's look at how the using control structure works. First, here's the source code again:

// required when using reflection, like `using` does
import scala.language.reflectiveCalls

object Control {

  def using[A <: { def close(): Unit }, B](param: A)(f: A => B): B =
    try {
      f(param)
    } finally {
      param.close()
    }

}

Here's how the using method works:

  • A and B both define types.
  • A can be an instance of any class that has a close() method. (This is known as a structural type in Scala.)
  • B can be any type.
  • The f parameter is something that takes a type A and transforms it to a type B.
  • The body of the code is very simple, it executes f with param, and calls the close() method on param, regardless of whether f(param) throws an exception.

Next, here's another look at the code that calls the using method:

using(MongoFactory.getConnection) { conn =>
  MongoFactory.getCollection(conn).save(mongoObj)
}

The first parameter passed to using is MongoFactory.getConnection, which is an instance of MongoConnection. The MongoConnection class has a close() method, so it's legal to pass this instance in as the first parameter. The second parameter passed in is an anonymous function that takes the parameter of type A (the MongoConnection) and converts it to type B, which is the result of the save(mongoObj) method call on the MongoCollection instance. The result of that save method call is a WriteResult instance, though I don't use that instance in this example.

Summary

I hope this discussion of David Pollak's using control structure is helpful. If you need a control structure that automatically calls a close method on an object, or wanted an example of how to create your own control structure, I hope this has been helpful.

You can find an excerpt of David Pollak's book at this URL on Google Books:

You can also find Mr. Pollak's Beginning Scala book here on Amazon.