prose :: and :: conz


Static typing doesn’t have to suck: Implicit Conversions

In my last Static typing doesn’t have to suck post, I introduced type inference. This allows the developer to have the perks of static type checking without the pain of redundantly labeling types.

Another feature that is handy in many languages is implicit type conversion. This is a language feature that allows a value of one type be coerced into another type without explicitly converting it. For a slightly contrived example consider taking a string containing an integer value and dividing it by 6. In Java, the code would look like this:

String fortyTwo = "42";
int div = fortyTwo / 6;

This of course won’t compile:

[error] /home/jbarnes/code/sandbox/src/main/java/pac/CoercionJava.java:6: error: bad operand types for binary operator '/'
[error] int div = fortyTwo / 6;
[error]                    ^
[error] first type: String
[error] second type: int
[error] 1 error

That is because there is no implicit conversion to make a String into an int. We have to instead use an explicit conversion:

int div = Integer.parseInt(fortyTwo) / 6;

But wouldn’t it be cool if we could do something like JavaScript with its deceptively familiar syntax? This code actually works the way you’d expect (div is equal to 7):

var fortyTwo = "42"
var div = fortyTwo / 6

Now to be fair to Java, it does feature some implicit conversions. I purposely selected something it cannot do but JavaScript can. But guess what? Scala can’t do this either. Take a look:

val fortyTwo = "42"
val div = fortyTwo / 6

[error] /home/jbarnes/code/sandbox/src/main/scala/pac/CoercionScala.scala:5: value / is not a member of java.lang.String
[error] val div = fortyTwo / 6
[error]                    ^
[error] one error found

So now what? Well the cool thing is that Scala let’s you declare implicit conversions much like C#. So we can make our code valid by writing a function that takes a String and returns an Int and marking it with the implicit keyword:

implicit def String2Int(s:String) = Integer.parseInt(s)

I don’t know how far C# takes this concept, but it doesn’t stop here with Scala. Notice that Scala figured out which conversion it needed to call to make it happen. It saw the *(Int) function which is not defined for String. So it searches among the implicit converters to find something that takes a String and returns something with a *(Int) function defined. This opens the door to some really neat stuff. For instance, if you’re a JVM junkie like me you know that most Java Apis specify time in milliseconds. It gets annoying when you want to express three hours, for instance. Since you don’t want to hardcode the multiplication, you would probably write a util method like this:

public static int hours(int millis) {
    return millis * 1000 * 60 * 60;
}
// Somewhere later in the code...
int threeHrs = hours(3);

Note that this assumes you don’t want to reuse it anywhere else in your code. You probably want to put it into a utility class, and now you’re stuck with appending that name to the front of the calls:

TimeUtil.hours(3);

With a Scala implicit conversion, you can write code that reads like English:

val threeHrs = 3 hours

No, seriously Mom, this can be done. First I should mention that when a function takes one or zero arguments, you can drop both the period and the parenthesis. Really, that code is syntactic sugar for this:

val threeHours = 3.hours()

And just as before, the Scala compiler sees that Int does not have an hours() function. So it looks for a conversion that will give it something with an hours() function. This class and converter do the trick:

case class MyInt(i:Int) {
  def hours() = i * 1000 * 60 * 60
}

implicit def MakeMyInt(i:Int) = MyInt(i)

Shout out to Lift for inspiring the 3 hours example in the Helpers object.

As you can see from these quick examples, you can have nice things like implicit conversions and still have the assurance of static typing. Keep your eyes open for a future post on structural typing, which is a completely foreign concept to Java. Soon after that I plan to get to lambdas, which while foreign to Java at the moment, is slated for Java 8.


Olde Comments
  1. […] relinquishing the perks of static type checking which I argue is a good thing. Next time, I plan to add implicit conversions to this discussion before moving on to structural typing and eventually […]

  2. jiminyChris says:

    […] at proze :: and :: conz, there’s all this talk about why static typing does not suck and justifications for it being a pretty all right thing sometimes. While all the points made there are wonderful and good, I’ve noticed one thing that–as […]

  3. […] previous post in my “Static typing doesn’t have to suck” series (now that I’m on post […]

  4. […] found I really enjoy: case classes, (?:case)+ objects, pattern matching, monadic types, lambdas, implicit conversions, and last but not least… optional […]

  5. […] object). Here I’m just treating the prop as an Int. We can actually do this. This is where an implicit conversion comes into play. Let’s add one to our properties […]

Tagged with: scala (41), java (22), static-typing (16), javascript (6)