Object Commando languages, development and design


OCaml in the Real World

There's a great video of a talk given by Yaron Minsky on his blog that discusses why Jane Street chose to go with OCaml. It's definitely worth the time to watch. What's interesting about the decision was the casualness of it and the fact that it was based on merit and success. Often times at organizations the standard language is decreed. Yaron describes more of a decision based on track record. OCaml was used by Yaron for a research project there, it went well, so more people were brought in to work on it. It turned out it was easier to find good developers if you advertised for OCaml developers. I thought this was interesting, because it goes against what is a fairly commonly held belief in our industry.

Lower Cost for Reuse

One interesting point Yaron makes on the technical merits of OCaml was on reuse. He describes a very typical copy and paste problem in larger code bases. He talks about how this was much worse in object oriented languages than it was in OCaml. When pressed for more details he didn't have any hard proof but discussed higher order functions contributes to this. I agree with him on the less code duplication and cleaner code of OCaml. It's true that duplicate code is a sign that some refactoring needs to take place, but why doesn't it? We all know that duplicated code is bad. I think the reason this is worse in object oriented languages is because the barrier to entry is high on reuse. To have a small piece of reusable code, it must be put into a Class, if it's an instance method, you need to create an instance of it etc. If you have a few lines that are duplicated between two classes, what do you do?

  • Create a new class C (3 - 5 lines of code)
  • Create a method in C that wraps those few lines (3 lines of code)
  • Create an instance of that class in Class A (1 line of code)
  • Swap out the duplicate code for a call to the shared code (swap 3 lines for 1)
  • Create an instance of that class in Class B (1 line of code)
  • Swap out the duplicate code for a call to the shared code (swap 3 lines for 1)

Is this worth it? We just traded 3 lines of duplicate code for 10+. In the Java world this is still worth it, but it did take quite a bit of work to refactor those 3 lines. Coincidentally, we have just about the same amount of duplicate code as before (i.e. creating the instance of class C is the same, so is the method call). The benefit here is that the business logic isn't what is duplicated, it's the fluff code. So if the business logic is centralized, we have achieved quite a bit, but what about the duplication of the fluff code? In OCaml the steps would be

  • Create a new function (1 line)
  • Add those few common lines (3 lines)
  • Swap out the duplicate code in A for a call to the shared code (3 lines for 1)
  • Swap out the duplicate code in B for a call to the shared code (3 lines for 1)

The fluff in defining this shared code is minimal, because defining a function is minimal.


Type Inference vs. Duck Typing

I've been working with JavaFX 1.0 lately, which has a new language called JavaFX Script. The language is based on Java, but is intended to make it easier and more concise to write Swing GUIs. The language has some interesting features and the first one I noticed was Type Inference. Having done some work in OCaml, I was pretty excited to see this. One point of confusion that I think a lot of people have is the difference between duck typing and type inference. It is not necessary to explicitly define the type in either of these type systems, so they look very similar on the surface. Dig a little deeper, and they are actually quite different.

Duck Typing

Duck Typing is a dynamic language concept that boils down to this: if an object responds to a message, that's all we need to know. Put another way, we may know that the object we're dealing with is an Employee, and we know Employee has a calculatePay() method, but at runtime, the fact that the object is an Employee doesn't matter, all that matters is that the object happens to have a calculatePay() method. Later, when we add a Consultant class, that has a calculatePay() method, we can treat it as if it were an Employee (in this particular case). The key point here is that it is dynamic. Only at run time does this stuff happen.

Type Inference

Type inference is when the compiler determines what type an object is based on the operations that are performed on it. The key part to this is the compiler makes this check, it is not at runtime. As an example, if we had the simple code:

private String example = "text";

Is the String declaration above really necessary? It's quite obvious that example is a String, since it is assigned the value right there. Now if we tried to treat the example as an Integer, it would fail. It would fail not because it doesn't have the right method, but because it's not the right type. Another example is below:

public int add(int x, int y)
  return x + y;

Here we have defined x and y as integers. With type inference, we would specify x and y and the compiler would know that since + was used on it, it must be a Number. With JavaFX, trying to pass a String into a type infered method that expects a string will result in a compile time error (and if using Netbeans, a nice set of red marks).