Ich Bin Mblinner

Surge Retro

I was lucky enough to present at Surge 2012, a great devops focused conference put on by OmniTi in Baltimore. I got a chance to talk about some of the stuff I’ve been doing at work, namely a fairly novel distributed system we’re building named Sirius.

I’d never been before, though some of my cow-orkers have, and seemed to enjoy it. I felt a little big Groucho Marx about the whole thing, not really sure if I wanted to go to a conference that would have me as a presenter, but I ended up being glad I did.

One fun moment:

At a bar after the speaker’s dinner, I notice the guy sitting next to me is really into the ball game. We start talking about baseball, how wonky the one game playoff is, how crazy things will be next year with all the inter-league play. Somehow we got from there to DTrace, the tracing framework for Solaris, and other operating systems.

Turns out the guy I was talking to knew his DTrace stuff, I mean really knew it. A few minutes into the conversation I realized I was talking to one of the co-authors of DTrace, a guy named Bryan Cantrill.

Unicorns and Strong Typing

There’s a scene in just about any Victorian period movie where a gentleman take off his glove and slaps another gentleman across the face in it. Or, if they’re going for historical accuracy, perhaps just throws it on the ground at his feet. A duel follows shortly after.

The modern equivalent to this ritual is to start a discussion on strong and weak typing. If you’re talking to a Javascript programmer, claim strong typing is good. If you’re talking to a Java programmer, claim weak typing is good. Then chose your weapons.

Where was I? Right, Unicorns. They don’t exist. Neither does strong typing. Or weak typing. More accurately, there does not currently exist a useful definition of the two terms that is widely accepted, and which can be used as the basis for a rational conversation about their relative merits. This is why the terms are only good for starting fights.

Don’t believe me? Let’s take a look at the definitions provided by that ultimate source of truth, Wikipedia.

In computer science and computer programming, a type system is said to feature strong typing when it specifies one or more restrictions on how operations involving values of different data types can be intermixed. The opposite of strong typing is weak typing.

Great, so it’s strongly typed if it “specifies one or more restrictions on how operations involving values of different types can be intermixed”. And its opposite is weak typing. Let’s see what Wikipedia has to say about that.

In computer science, weak typing (a.k.a. loose typing) is a property attributed to the type systems of some programming languages. It is the opposite of strong typing, and consequently the term weak typing has a number of different meanings, just as “strong typing” does.

Well okay then, so we’ve confirmed that weak typing is indeed the opposite of strong typing. That should clear things up. Let’s talk about something else.

Implicit Conversions

Pop quiz, what does the following Ruby and Scala code do that the Javascript code doesn’t?

1
2
3
4
5
6
ruby> foo = 1
 => 1
ruby> bar = 1.0
 => 1.0
ruby> baz = foo + bar
 => 2.0
1
2
3
4
5
6
7
8
scala> val foo = 1
foo: Int = 1

scala> val bar = 1.0
bar: Double = 1.0

scala> val baz = foo + bar
baz: Double = 2.0
1
2
3
4
5
6
javascript> foo = 1
1
javascript> bar = 1.0
1
javascript> baz = foo + bar
2

They all appear to be adding an integer and a decimal number together, but all is not as it seems.

In most languages, an integer and a floating point number are very different things, at least to the compiler. Signed integers are generally represented as two’s complement while decimals are represented with the IEEE’s floating point standard.

This means that to a computer, 1 and 1.0 may not be the same thing. One may be two’s complement, and the other floating point, so 1 and 1.0 may actually be represented by a different sequence of bytes! You can’t directly add them together.

What Ruby and Scala both do is implicitly convert the two’s complement integer into a floating point number before doing the addition. This is most apparently in the Scala case, where Scala tells us that the result of adding together an Int and a Double is, indeed, a Double.

Javascript, on the other hand, doesn’t need to do this conversion because it has only a single numeric type, Number, which is represented as floating point. So in Javascript, 1 and 1.0 are pretty much the same, unlike Ruby and Scala.

Implicit conversions are at the heart of most discussions on strong and weak typing, as is hinted at by Wikipedia definition of strong typing - “…specifies one or more restrictions on how operations involving values of different data types can be intermixed”. The intuition here is that if you can’t reasonably perform an operation on values of two different types, possibly by implicitly converting one type to another, than the language should disallow it.

The problem with that definition is that it fits almost every language, for some definition of reasonable. Without implicit conversions, we’d lose a whole ton of convenience, like adding an integer and double together, or concatenating a number on to a string, or assigning an unboxed int to an Integer in Java. However, the more aggressive a language gets with its implicit conversions, the more dangerous they can get. Java is rather conservative here which is why its often called strongly typed, though the conversion from unboxed to boxed numbers, for instance, can have very surprising effects on a program’s memory usage and runtime.

So what people generally mean when they say weakly typed is ‘holy crap that language does implicit conversions which I think make no bloody sense, and which frighten and concern me’. This, of course, is why Javascript is the example most folks trot out when talking about weakly typed languages. It does some seriously bizarre implicit conversions.

Anyhow, that’s why most discussions about strong and weak typing just degenerate into anarchy. The only workable definition is that a language is weakly typed is that it does implicit conversions you consider bizzare, and it’s strongly typed if it doesn’t. Computer scientists don’t seem to use the terms anymore, they prefer to talk about the type safety of a given type system.

While this is a topic for another day, type safety has to do with the guarantees that a languages typesystem makes. For instance, using the Scala type system guarantees that you’ll spend a non-zero amount of time trying to remember what the compiler can and cannot infer, and using the Javascript typesystem guarantees that you will begin drinking heavily.

As a side note, Scala give programmers the power to define their own implicit conversions. Here, for instance, is an implicit conversion that will convert from a Scala function to a Java Runnable.

1
2
3
implicit def functionToRunnable(fn: () => Unit) = new Runnable() {
  def run() = fn()
}

With that implicit defined somewhere in a project, the Scala compiler will convert Scala functions to Runnables when it has a Function and needs a Runnable. It may seem that exposing this sort of power to application developers is dangerous, but rest assured, it was added to the language only after it was discovered that shipping butcher knives without handles to the entire Scala userbase would be prohibitively expensive.

Scala Custom Exceptions

At work, we’ve been doing a lot of our new stuff in Scala lately. One thing that we’re writing is a client, packaged up as a jar, that needs to work from both Scala and Java code. For the most part, the interop between Java and Scala is smooth, but there are occasional strange hiccups.

Scala hasn’t really given me much as much cause to define custom exceptions as I find in Java. Partially this is because we’re doing a lot of work in Akka, which has an Erlang like ‘let it fail’ model. Part of it has to do with Scala’s Option, I find myself returning a None in a lot of situations where I might have thrown an exception in Java.

So when I finally had to create a custom exception for Java interop, I ran into one a bit of a rough edge. Creating a simple custom exception class is, of course, a one-liner.

1
class ScalaCustomException(msg: String) extends RuntimeException(msg)

(Thanks Mishu, for noticing I forgot to put the superconstructor call here)

The problem comes in when you need two constructors, one that just takes a message, and one that takes a message and a cause. This is trivial to do in Java.

1
2
3
4
5
6
7
8
9
10
11
public class CustomException extends RuntimeException {
  
  public CustomException(String msg){
      super(msg);
  }
  
  public CustomException(String msg, Throwable cause){
      super(msg, cause);
  }
  
}

But next to impossible to do in Scala. Scala requires that every class have a single primary constructor, and that constructor is the only one that’s allowed to call a superclass constructor.

The cleanest thing I could come up with was to use the one argument constructor, which only sets a message, and then set the cause after it was constructed. I wrapped that logic up into some methods on the Exception’s companion object so I could use it as a factory.

1
2
3
4
5
object ScalaCustomException {
  def create(msg: String) : ScalaCustomException = new ScalaCustomException(msg)

  def create(msg: String, cause: Throwable) = new ScalaCustomException(msg).initCause(cause)
}

This works well enough without setting a cause.

1
2
3
4
scala> throw CustomException.create("bad things")
CustomException
  at CustomException$.create(CustomExceptionScala.scala:6)
  ...

And with setting a cause.

1
2
3
4
5
6
7
8
9
scala> val cause = new RuntimeException("cause")
cause: java.lang.RuntimeException = java.lang.RuntimeException: cause

scala> throw ScalaCustomException.create("bad things", cause)
ScalaCustomException
  at ScalaCustomException$.create(CustomExceptionScala.scala:8)
  ...
Caused by: java.lang.RuntimeException: cause
  ...