Tips and Tricks

Pimping Libraries

An idiom for cleaner pimping of libraries in Scala

In dynamic languages like JavaScript and Ruby you can modify existing classes, including system classes, with extra methods. This can be a very handy, if dangerous, technique.

Scala, being a static language does not allow this same technique. But it does allow the use of implicit functions to get the same effect. For example the standard idiom to add sine and cosine methods to the Double class is

class PimpedDouble(x:Double){
  def sin = Math.sin(x)
  def cos = Math.cos(x)
}
implicit def pimpDouble(x:Double) = new PimpedDouble(x)

This has the effect of adding sin and cos methods to Double, though what is actually happening is that Double values are automatically converted to PimpedDouble values when doing so would correctly compile.

This is very clever and very handy, but the idiom is a little clumsy, compared to most of Scala's elegant features. It is annoying to have to invent two names PimpedDouble and pimpDouble that are never referred to anywhere else in the code.

Can we do better? Yes we can. We can make the extra class be an anonymous class, which leaves only one arbitrary unreferenced name and also reduces the size of the code.

implicit def pimpDouble(x:Double) = new {
  def sin = Math.sin(x)
  def cos = Math.cos(x)
}

That seems a lot nicer to me.

Using either of the above techniques you can now do things like

  val x = 0.5 cos
  val y = 0.5 sin

which is taking the cosine and sine of the Double value 0.5

(Thanks to Daniel whose stackoverflow posting first brought this idiom to my attention.)

Making it easier to add attributes to an XML element

In most respects Scala makes it very easy to handle XML, but there are a few things that are hard to do. One is changing the value of an existing attribute on an element, or adding a new attribute to an element.

The simplest way I found to add new attributes c="CCC" d="DDD" is to do:

val modified = elem %
                new UnprefixedAttribute("c","CCC",Null) %
                new UnprefixedAttribute("d","DDD",Null)

This is a bit verbose. What if instead you could do

val modified = elem % Map( "c"->"CCC", "d"->"DDD" )

Well you can, if you add the following implicit somewhere in scope:

    implicit def pimp(elem:Elem) = new {
      def %(attrs:Map[String,String]) = {
        val seq = for( (n,v) <- attrs ) yield new UnprefixedAttribute(n,v,Null)
        (elem /: seq) ( _ % _ )
      }
    }

This uses the library pimping pattern discussed elsewhere to effectively add a new version of the % operator to Elem that takes a Map of attributes.

The new % operator uses a for-yield construct to convert the attrs Map into a sequence of UnprefixedAttribute objects. It then uses the /: fold operator to repeatedly apply the built-in % operator, reducing down to an element with all the attributes added.

Adding a ! factorial operator

If you learned about recursion you probably were given the factorial function as a simple example. Here it is in Scala:

def factorial(n:Int):Int = if(n==0) 1 else n * factorial(n-1)

Very nice. Now you can do factorial(6) to get the answer 720.

But would it not be nicer if you could use standard mathematical notation and do 6!

Well you can. Simply add this simple pimping implicit somewhere in scope:

implicit def pimp(i:Int) = new { def ! = factorial(i) }

Now you can use the ! operator after any integer. To avoid confusing the compiler, however, you may have to add some extra parentheses:

(3!) + (3!)

(3+3)!

Can we do better? Well if we avoid using recursion we can do it all in one line:

implicit def pimp(n:Int) = new { def ! = ((1 to n) :\ 1) ( _ * _ ) }

Here we are generating the integers 1,2,3,...,n and using the :/ fold operator to multiply them all together.

Adding a exponentiation operator to Double

Using the same pattern that we used to add the ! factorial operator to Int we can add an ** exponentiation operator to Double.


def pow(x:Double,k:Int):Double = if(k==1)
   x
else
   (if (k%2==0) 1.0 else x) * pow(x*x,k/2)

implicit def pimp(x:Double) = new { def **(k:Int) = pow(x,k) }

You can now, for example, type in 2.0 ** 8 to get 256.0 or Math.Pi ** 4 to get 97.40909103400243

How a Scala script can specify what JARs should be added to its CLASSPATH

The reason the Scala programming language has such a name is that it is meant to be scalable, i.e. good for both small scripts and large software systems. I am already convinced that Scala is as good, if not better than Java for the large-scale development, but what about the small scale?

Well it turns out that on Linux if you chmod +x a scala script you can make it executable with a bit of shebang magic as shown by this complete, runnable script:

#!/bin/sh
exec scala $0 $@
!#
println("Hello World"!")

(You do have to make sure that "scala" is in your executable path.)

But what if you are using a scala script to control an existing Scala or Java system? It would be nice to express the CLASSPATH requirements in the script itself rather than depending on the calling environment to be configured correctly. Well, I came up with this convenient idiom to collect all the JAR files in a lib directory and add them to the CLASSPATH:

#!/bin/sh
L=`dirname $0`/../lib
cp=`echo $L/*.jar|sed 's/ /:/g'`
exec scala -classpath $cp $0 $@
!#
import com.my.special.World
val world = new World
world.hello

This assumes that all the required JAR files are in directory ../lib relative to the script file.

[This was originally posted on my blog.]

- valtrex buy online no prescription - where to buy asacol - cell spy phone - generic levitra -