prose :: and :: conz


Static typing doesn’t have to suck: Inference

In a previous post, I shared why I have 180’ed my preference on static typing. I’d like to share with you some snippets of code that show how a designer language (well… I’d argue that Scala isn’t a “designer language” based on his definition, but whatever) can do some really nice things to let the type system work for you. First, let’s look at this declaration in Java:

final String name = "Joe";

See the problem? What is the type of name? String, right? How do you know? Is it the fact that name is preceded by String? What about the fact that I assigned name the value "Joe"?! Why can’t it just know that it’s a String because… well… it is a String? Just for good measure, I even annotated my variable with final to keep anybody from getting smart and pointing out that it could be later changed to a different type had I not explicitly declared it a String. The good news is a language can figure out the type by inference. Let’s look at the analogous declaration in Scala:

val name = "Joe"

Ah, much better. Just so you know, val makes this an immutable value (as opposed to using var). So even if you wanted to get cute and change it to an Int, well you can’t do that. You can’t even change it to another String like "Bob" (In fact, you can’t change the type if it’s a var either.)

This also works for the return type of a function. In Java, one must explicitly declare the return type. For instance:

public String getStatus() {
    return "Good";
}

As before, you can drop the String declaration in Scala:

def getStatus() = {
  return "Good"
}

I know what you’re thinking (yes, YOU, Mom). Big deal, right? I saved a few chars. By itself these two simple examples don’t show much. But once you start stringing these together, it adds up. I’m not just talking the number of avoided keystrokes adds up. The ease of changing the code increases. What if we had this code:

def getStatus() = "Good"
val status = getStatus()
if(status == "Good") Console.println("It's all good")

(Notice that return is optional since the last line is always an implicit return and the curly braces aren’t needed for one-liners). Compared to the Java implementation, I have twice left off String. This is handy if I one day decide that a String isn’t good enough for my status. Perhaps later I decide to define a class to hold a String and an error code. All I have to do is change the value returned by the function, and update the if statement where I have consumed the value. I have found this ability very handy in my own coding.

Type inference is especially nice when you are in generics land. With Java, one is stuck with annotating types all over the place. Maps are especially ugly because not only do you have two types to annotate twice, there’s no way to express the entries in a list. You have to add each one explicitly. Take this map declaration/population for instance:

Map<String, Integer> text2Int = new HashMap<String, Integer>();
text2Int.put("one", 1);
text2Int.put("two", 2);
text2Int.put("three", 3);

The Scala version is way better:

val text2Int = Map("one" -> 1, "two" -> 2, "three" -> 3)

Not only did I not have to explicitly declare this a Map[String, Int], I didn’t have to mention it at all because type inference was able to see what type of objects I put in my Map.

The benefits of type inference continue to add up when you consider other language features such as lambdas. Inference gives you the feel of a dynamic language by lifting the developer’s responsibility to label everything (although you can label types if you so desire), but without 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 lambdas.


Olde Comments
  1. […] next blog post will highlight some of the Scala language features that helped flip my position. And thanks as […]

  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 […]

  3. […] 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 […]

  4. […] of my types into an arbitrarily-deep nesting of Tuple2′s. If you’ve been following my Static typing doesn’t have to suck series, this post will tie together many of the features I’ve […]

  5. […] inference I really miss type inference. It is an outstanding feature that makes static-typing so much better. I really shouldn’t have to tell Java that I’m giving it a […]

  6. […] we see a lambda which takes a pair of integers (the type is statically known due to type inference) and returns an integer, hence we have a binary operator on the set of integers. In particular, […]

  7. […] I use my PropertyUtil to hide uninteresting details. Thanks to type inference, get is properly typed as returning an Int. We can update our specification to set the property […]

Tagged with: scala (41), static-typing (16)