a little madness

A man needs a little madness, or else he never dares cut the rope and be free -Nikos Kazantzakis

Zutubi

Languages, Complexity and Shifting Work

One of the things that bothers me about the rise of dynamic languages is the nagging thought that work is being shifted the wrong way. Generally speaking, we programmers all become more productive as work is shifted down to lower levels. The smarter the toolchain, the less we need to bother with incidental details, leaving us to focus on Real Problems. Sure, someone needs to program that toolchain, but once that is done by the few the benefits can be reaped by the many.

What does this have to do with dynamic languages? Well, a lot of the productivity benefits of these languages come from their support for higher levels of abstraction. Think first class functions, closures, completely dynamic dispatch and so on. Why is it that dynamic languages all seem to have these features, where many statically-typed languages don’t? I believe a primary reason is that these features are easier to implement in dynamic languages. It’s not that it is impossible to support such features in static languages — in fact many static languages do support them — but rather that creating a flexible enough type system is a challenge.

Probably the most obvious example is duck typing. This is a feature of dynamic languages that removes complexity from the language implementation. With duck-typing, the implementation need not inspect or infer anything, it just tries its best to dispatch at runtime and throws an error if it can’t. Compare this with the complexity of implementing a static type system capable of full inference and/or a reasonable alternative like Scala’s Structural Types.

So where is the problem? Well, having these features in dynamic languages is a wonderful thing, but it comes at a cost:

  • No static verification. Without this verification, we need to do more work to test our code. And because testing isn’t perfect, we risk more bugs.
  • Less-precisely specified APIs. As APIs contain no type information, they can be harder to read and learn. Documentation helps, but this kind of documentation comes for free (with verification by a compiler) in a statically-typed language.

Essentially, the dynamic languages are giving us more flexibility, but at the same time are shifting other work our way. Shouldn’t we aim for more? From what we know about shifting work, shouldn’t we be demanding a language which tackles the complex issues head-on to deliver us this flexibility without the costs?

Are there languages that achieve this already? Classics like ML and Haskell, along with newcomers like Scala at least take aim at these harder issues. The biggest problem has always been pushing the complexity down into the language implementation without having it leak too much into the language itself. This is one of the greater challenges in software, but the closer we get to nailing it the more productive we’ll all become.

Liked this post? Share it!

Leave a Reply