Are Dynamically Typed Languages The Next Big Thing?

I’ve been thinking for months about dynamically typed languages (languages like Perl, Python and PHP) and how they compare to the traditional statically typed languages (such as C, C++, Java and C#). In a way you get the feeling dynamically typed languages are so much more simple and productive than the statically typed ones, on the other hand you see their problem: tooling.

First I’ll define what dynamically typed languages and statically typed languages are. Statically typed languages are languages that that force you to explicitly state the (return) types of your variables, functions and parameters. For example, like in C:

int mult(int a, int b) {
return a * b;
}

With dynamic languages, on the other hand, you don’t have to define types at all. The same piece of code in Python would look like this:

def mutl(a, b):
return a * b;

The good
What’s clear is that with dynamic languages you have to write less code. Also, because of their dynamic nature, some typing problems static languages have are non-existant. For example, if you try to use a hashtable within a hashtable (a double-layered hashtable). In C# 1.0 that would look something like this:

Hashtable ht = new Hashtable();
ht["something"] = new Hashtable();
((Hashtable)ht["something"])["someObj"] = new SomeObj();
((SomeObj)((Hashtable)ht["something"])["someObj"]).SomeMethod();

Now, let’s do the same thing in Python:

ht = {}
ht["something"] = {}
ht["something"]["someObj"] = SomeObj()
ht["something"]["someObj"].SomeMethod();

Sure, you would say generics would solve this problem. But initially it just stacks up on the typing. In C# 2.0 the same code would look like this:

Hashtable> ht =
new Hashtable>();
ht["something"] = new Hashtable();
ht["something"]["someObj"] = new SomeObj();
ht["something"]["someObj"].SomeMethod();

It’s easier to read than the C# 1.0 code, but admit it, it ain’t as pretty as the Python version.

If you wonder if you’d ever need a double-layered hashtable, yes, in a project I did last year we needed one. And yes, we used the C# 1.0 code I showed you. Not a pretty sight.

So, obviously, dynamically typed languages won’t let you deal with complex typing stuff. One tradeoff is speed. Usually code can be more optimized if it knows the variable types in advance. The good thing is that the code you write is simpler, it’s closer to what your pseudo code algorithm would look like. There’s less “formality” to deal with, less coding overhead. Personally I think this is the direction in which programming language should develop. We started out writing bits, then “abstracted” that to assembly code, on to C, C++ and other 3GLs (3rd Generation Languages). In a way I think dynamically typed languages feel right, they seem to be a logical next step, the fourth generation of programming languages.

So, are dynamically typed languages really the next big thing?

My problem with dynamically typed languages
If all we’d use were plain text editors to write our code, I’d definately answer that with a firm “Yes”. However, good developers do not use simple text editors to write their code. They use IDEs like Visual Studio and Eclipse. These tools not only colour highlight your code, but often can assist you in many other ways. Two important ones are code completion and refactoring.

Code completion works as follows. In Eclipse, you start writing some code:

void doSomething(ArrayList ar) {

The IDE will now know that when I’m talking about ar within the scope of this method, I mean an ArrayList. So, when I would now type:

ar.

The IDE will know what could follow after that, and a list of methods and fields would pop up. The IDE can do this because it knows the type of ar. However, now let’s try to do the same thing in Python:

def doSomething(ar):

what would an IDE know about ar? Nothing. Nothing useful at all. If we’d be at runtime, we’d know, but we’re not. People don’t develop at runtime. Some dynamically typed languages have an interactive shell, like Python, where this information could be supplied, but again, you don’t develop your applications in an interactive shell. So, code completion like IDEs like Eclipse and Visual Studio does is per definition impossible with dynamically typed languages like Python. Some Python IDEs try to guess the type, for example by reading other code to see what kind of values are assigned to it, but this doesn’t work well in many occasions and it can never be fully accurate.

Same goes for refactoring. One refactoring I use a lot is renaming a method. Let’s look at this piece of Java code:

class SomeClass {
public void DoIt() {
// ...
}
}
class Caller {
public void call(SomeClass d) {
d.DoIt();
}
}
Now, when I ask Eclipse to rename the method DoIt to DoItNow it will, beside renaming the method, also find all occurences of that method being called on an object of the type SomeClass. So the resulting code would be:
class SomeClass {
public void DoItNow() {
// ...
}
}
class Caller {
public void call(SomeClass d) {
d.DoItNow();
}
}
Now, let's see why this won't work in Python:
class SomeClass:
def DoIt(self):
pass
def call(d):
d.DoIt()
If I want to rename the method DoIt of the SomeClass class to DoItNow, do I have to change the call in the call function aswell? You can't possibly tell. I'm not sure what type d is of, it could be SomeOtherClass with a method with the same name.
Another difference between the interpreters/compilers of dynamically typed languages and statically typed languages are the errors they detect on "compile" time (or in case of interpreters, before something gets actually run). A compiler like Java's or C#'s will immediately detect errors like not defined variables, wrong values assigned to variables, non-existant methods called on objects and many other things. However, all a dynamically typed language "compiler" can do is see if the code is syntactically correct. None of the things mentioned can be checked because of the language's dynamic nature. These problems only pop-up at runtime. So a way to find them is doing whitebox testing, which basically involves testing every possible path through your code. In a perfect world you'd do such testing anyway, but in real world applications it's too much work.
Some people argue that you'd never be able to check everything on compile time anyway, so why not just move everything to runtime, when you're for certain. It's true that you can't check everything upfront, but I think that the more errors you detect as quickly as possible, the better. When I hit save in Eclipse my code is compiled. When those errors pop-up they're easier to fix then when I just start running my code and wait for it to crash.
Conclusion
Sigh. All my life I hoped to find the ideal kind of language for everything. But once again it shows that such a thing does not exist. If we'd use dynamically typed languages, we'd be able to produce code faster, as we have to type less. But by doing that we'd also abbandon the opportunities statically typed languages offered, such as automated refactoring and perfect code completion. Not having to switch to documentation all the time, to see which objects had what methods, saved so much time and allowed your brain to be used for something else than holding all the classes and their methods. But with dynamically typed languages we would be back to that, in that respect it's a step backward. But in many projects this won't be a concern, particulary in scripting. If you quickly want something done, want to parse a file do something with it, it's far more convenient to use a language like Python or Perl.
Another application for dynamically typed languages could be teaching. In the beginning it's important to primarily focus on what your program should do and how it should do it. That's why people pick pascal over C. Pascal helps you detect errors (for example array index out of bounds errors) and doesn't let you use pointers as much as C. Using Python would simplify it a bit more. You no longer have to be aware of typing issues, those are things that you will learn to deal with later, let's first focus on the fundamentals.