Revisiting Factorials in Scala

In my earlier post I showcased doing a simple factorial code kata using scala and today as I was driving home from work I was thinking… isn’t there some way to dynamically add methods to an object so that I can just write 10! and have it compute the factorial?

The answer is yes, kind of. You don’t really define a new method that gets tacked onto an existing type, but rather define an implicit method that gets called to “implicitly” convert one type to another.

With this in mind, I cracked open the scala commandline and tried the following out:

class RicherInt(n:Int){ def ! = (1 to n).foldLeft(n)(_*_) }

implicit def intToRicherInt(n:Int) = new RicherInt(n)

6! 

The result was res3: Int = 720. Woot! Now I tried it out by rewriting my specification to look like this:

import org.specs._

class FactorialSpec extends Specification{
  "factorial" should {
    ...
    "return 6*5*4*3*2*1 for n = 6" in {
      (6!) must be equalTo(6*5*4*3*2*1)
    }
  }
}   

To make this work I needed to import the implicit def rather than just have it lying around naked like you can on the commandline. So I created a AwesomeInt class and an object to hold the implicit method:

class AwesomeInt(n:Int){
  def ! = (1 to n).foldLeft(1)(_*_)
} 
object Converter{
  implicit def intToAwesomeInt(n:Int) = new AwesomeInt(n)
}

and updated the specification to import the Converter object.

import org.specs.Specification
import Converter._

class FactorialSpec extends Specification{
  "factorial" should {
    ...
    "return 6*5*4*3*2*1 for n = 6" in {
      (6!) must be equalTo(6*5*4*3*2*1)
  }
}   

And presto! All the examples in my specification passed. Perhaps my only nitpick is I wish I could figure out how to make the example read like the below for much cleaner, plain english looking specifications.

6! must be equalTo(6*5*4*3*2*1)
  • http://tersesystems.com Will Sargent

    I love implicits. It’s like Ruby monkeypatching, only far more targeted and precise.