Scala Implicit Conversion

Posted in java by pedro | Tuesday, July 14th, 2009 at 6:09 pm

I’ve just finished Programming in Scala by Martin Odersky. So in next few post I will describe my thoughts about Scala. Shortly I recommend you to get know something about this language. I quote:

"If I were to pick a language to use today other than Java, it would be Scala" by James Gosling

"I can honestly say if someone had shown me the Programming in Scala book by by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I’d probably have never created Groovy." by James Strachan.

Interesting, isn’t it?

Scala has a lot of futures we do not have in java, one thing I like about scala is that most of new features  are de facto libraries, this libraries simply extend language (the name scala comes from scalable language). 

In this post I will focus on implicit conversions. It is similar to java cast, which are explicit, but of course implicit conversion are more powerful feature, which is used in scala to extend existing libraries easier.

Implicit conversion is a function which takes one type as parameter and return other type. Example in java space will be String.valueOf(int i) which takes int type and return String object. So where is the fun in this :)

The fun comes from fact that this functions are applied implicitly by compiler with full type check. To do this compiler require to follow some rules:

  1. Implicit conversion must be in scope as single identifier, or be associated with the source or target type.

    /* put conversion into scope */
    import Preamble._  /* many libraries import in this way library implicit conversions"
    /* or  as companion object */
    class Person { ... }
    object Person {
    /* implicit conversions goes here for Person type */
    }
    
  2. One conversion at the time, so there isn’t implicit conversion chaining.
  3. There may be only one way to apply implicit conversion, otherwise compiler rise error.
  4. And the last is of course that explicit has priority.

Writing implicit conversion is very easy, we just put implicit keyword before method, and we are done. The name of the implicit conversion depends on developer, I mostly saw type2target convention as example some implicit conversion from Predef: any2ArrowAssoc, int2double etc. Of course there are also typeToTarget and typeWrapper as well.

Want to assign double to int just wirte this implicit and it works.

scala>  implicit def double2int(d:Double): Int = d.toInt
scala> val i : Int = 3.5

Ok so what we can do with implicit conversions. Implicit conversion is tried in such situations:

  1. As expected type (extended cast alike).
  2. Receiver conversion.
  3. Also as implicit parameters

First rule applies in many cases, as behind the scene action. For example assume this code:

val d : Double = 3 /* 3 is Integer */
/* this code is translated by compiler into val d: Double - Predef.int2double(3) */

It works perfectly because in fact compiler is using Predef.int2double implicit conversion. We can do in such way proper object translation to use it with current libraries.

Map( "first"->"Test", "second"->"Code")

It looks like a special syntax but in fact it is just implicit conversion in action. The code is translated into:

  Map.apply(any2ArrowAssoc("first").->("Test"), any2ArrowAssoc("second").->("Code"))

I omit generics and Predef package to make this code more readable, as we see this "syntax" in fact use any2ArrowAssoc implicit conversion defined in Predef.

As all we know with great power, comes great responsibility. It may be hard to know what is going on with my code, when implicit conversions are overused. So key fact is that always we can use implicit conversion as normal method and call it explicit. Second scala compiler has -Xprint:typer option parameter which can be use to show scala code after applying implicit conversions. I was using it to show the code of Map pseudo-syntax. Example looks like this:

/* scala code Test.scala */
object Test extends Application {
  Map( "first"->"Test", "second"->"Code")
}

Console output

pedro$ scalac -Xprint:typer Test.scala
[[syntax trees at end of typer]]// Scala source: Test.scala
package  {
  final object Test extends java.lang.Object with Application with ScalaObject {
    def this(): object Test = {
      Test.super.this();
      ()
    };
    scala.this.Predef.Map.apply[java.lang.String, java.lang.String](
scala.this.Predef.any2ArrowAssoc[java.lang.String]("first").->[java.lang.String]("Test"),
scala.this.Predef.any2ArrowAssoc[java.lang.String]("second").->[java.lang.String]("Code"))
  }
}

There are also implicit parameter which also use implict to add additional parameter to the method calls. Implicit conversion is quite simple but very powerful feature, isn’t it? What do you think about it? In my opinion is quite useful.

Leave a Reply

about me

My name is Sebastian Pietrowski. I've finished Warsaw University as Master degree. During my studies I started work for merlin.pl. The primary language I use is Java but I have also programmed in Python, Ruby and Scala. I worked as a technical solution architect at merlin.pl. infrastructure when we were moving from PL/SQL to J2EE. I engineering a great performance optimized solution that made the application 10 times faster than requirements and 85 times faster as original solution.

Currently, I am working as a Senior Expert at F.Hoffmann-La Roche to help define future roadmap in design and development of Enterprise software at Roche and Genentech and build adoption for new technologies. I'm continuously mentoring new developers, helping them understand how important test driven development is and empowering them to get better at their daily job. I'm involved in many activities which brings new technologies for better and faster development. You can find more details on my LinkedIn profile.

But don’t get me wrong, I am not your typical nerd. I'm a pleasant guy that you can drink a glass of wine with me and talk about a range of topics with. My leisure activities include playing basketball, soccer and listening to music. I try to be pragmatic while staying focused on application performance and tuning with success in my daily work.

My favorite quote from Yoda's and my life’s motto is: Do, or do not. There is no try.