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 typeB
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.