The QuickPimp Pattern

Posted by Mathias in [scala]

02 Dec 2010

Anyone turning to Scala for developing non-trivial applications will come across a number of more or less established Scala Design Patterns. One of the most widely-used ones is the “Pimp my Library” Pattern, which got it’s name from a short article Martin Odersky wrote in October 2006.

This pattern denotes the way in which you can augment (or “pimp”) an existing type with the equivalent of additional members that are not defined in the type itself but in some other place you have control over.

For example, the Scala library pimps the java.lang.String class with a toInt method returning the Int value of the string:

scala> val i = "123".toInt
i: Int = 123

In it’s typical incarnation the “Pimp my Library” pattern consists of two things:

  • A new type (the “rich wrapper”) that either wraps the to-be-pimped type or derives from it.
  • An implicit conversion from the underlying type (the “pimpee” ;^) to the rich wrapper.

For the example above these two ingredients correspond to:

  • The scala.collection.StringLike trait that defines toInt like this:
    def toInt: Int = java.lang.Integer.parseInt(toString)

  • An implicit conversion from String to scala.collection.immutable.StringOps, which implements the StringLike trait:
    implicit def augmentString(x: String): StringOps = new StringOps(x)

The “Pimp my Library” pattern makes types in Scala feel a bit like the “open classes” available in Ruby and other dynamic languages, however, without giving up static typing and without the risk of breaking existing code that usually comes with monkey patching. Additionally modern JVMs can completely optimize away the seeming overhead of the wrapper object instantiation.
Therefore this pattern is a great tool for making your code more concise and readable, not only when the pimpees live outside of your codebase. Even when you could just add another method to your underlying class you might decide not to in order to follow the principle of “separation of concerns”. For example, when you have a set of domain model classes living in one module of your project and business logic code spread out over a number of other modules, you could choose to define a number of model class pimps per business logic module. The pimps would allow you to keep your model classes free of code not belonging there, without giving up the convenience and readability of saying something like applicant.hire.

Quick Pimping

Having grown fond of model class pimps I repeatedly found myself slightly annoyed by the overhead of having to introduce dedicated rich wrappers just for adding one single method to a pimpee. A rich wrapper can be named arbitrarily (since it never has to be directly referred to), the JVM removes its instantiations, couldn’t we just get rid of it completely?

Once again: Structural types for the rescue!

The toInt pimp from above could just as well be defined like this:

implicit def string2toInt(s: String): { def toInt: Int } = new {
  def toInt: Int = java.lang.Integer.parseInt(s)
}

Clean, concise, no dedicated rich wrapper type in sight.
It seems perfect, doesn’t it?
It is, with one small caveat. Support for structural types in Scala internally relies on reflection. This makes QuickPimps slower than their “regular” siblings that are based on dedicated wrapper types.

However, as long as you are not using QuickPimps in performance critical parts of your application they can be a great addition to your pattern toolbox.

Cheers,
Mathias

View Comments