Thursday 19 November 2009

Implicit conversions in Scala

Scala provides a powerful feature called implicit conversion which you can use to augment existing classes with methods and fields. While Groovy achieves a similar result via the use of categories and metaclasses, Scala takes a static, compile-time approach. Implicit conversions are an important mechanism, among other things, for writing internal domain specific languages (DSLs). With conversions in place, I can write statements such as:

Scala's Int class does not support the "minutes" method but by adding an implicit conversion to a class which does, then the previous statement can compile and execute.

Here is the code to make it work:


I first define a SecondConverter class which converts a unit of time into its value in seconds. The SecondConverter defines methods called minutes, hours, seconds, days (and singular equivalents).

Then in the main method I define an implicit conversion called convert which is a normal method with the implicit appended to it. That method transforms an integer to an instance of SecondConverter. Because I have defined convert within the Example object, it is in scope for that object. Another way to bring an implicit conversion method in scope is to import it.

When encountering the statement 7.minutes, the compiler realizes that minutes is not a method of the Int class. Instead of throwing an error, it tries the implicit conversions that are in scope. As convert takes an Int as an input and produces something that has a minutes method it is selected, and eventually the compiler re-writes the statement 7.minutes as convert(7).minutes

I've written the implicit function inside the object, but it is possible to have it defined in a different file and use the Scala import functionality to bring it in scope. Scala implicit conversions are quite powerful but in some cases might be a bit tricky to understand / debug as the choice is conversion to apply is done automatically by the compiler.

Implicit conversions are a useful building block for creating domain specific languages in Scala. If the topic of DSL interests you, then I recommend you read this nice blog post: http://debasishg.blogspot.com/2008/05/designing-internal-dsls-in-scala.html

This concludes this post. So using the techniques described here, one might be able to come up with a DSL to write statements such as:

No comments:

Post a Comment