Thursday, November 13, 2008

The enormous problem with highly dynamic languages

So you're moving from an "old-school" language like C/C++ into a "new hotness" language like C#, and life is so much easier. Memory management is automatic, type information is part of the runtime, everything is dynamic. You can create these very simple expression to perform very complex operations, all auto-magically, and rapidly prototype applications like never before. Life is great, right?

Well, there's a small problem which is the 800lb gorilla in the ideology. See, there's two parts to a language enabling you to writing code which does what you want: letting you express what you want to do, and helping you not express what you didn't want to do. The former is aided by higher level abstractions, patterns, powerful expression syntax, API libraries, etc. The latter is aided by strong compile-time checking, API/structure transparency, clear and predictable behavior, etc. A good language balances both of these.

The problem with low-level languages is that they have a lot of the latter, without much of the former. The problem with highly dynamic languages is that they have a lot of the former, at the expense of the latter. The big problem with languages lacking the latter is that lacking the former just slows you down, whereas lacking the latter makes your applications fundamentally less reliable and more prone to subtle systemic problems. The huge problem is that there's no way around that problem: no matter how clean your structure and methodologies, you're always forced to perform runtime verification, and it's nearly impossible to eliminate systemic errors because the runtime implementation is so convoluted and obtuse.

I would not be surprised if we see a resurgence of "native" code development because of these issues, because they are so fundamentally intractable in dynamic languages. I know I shutter to think of trying to build a reliable .NET application of any meaningful complexity. We shall see.