Counterattack of the Weenies
Filed under: dynamic+languagesOver at hacknot, there's an article criticizing dynamic language "weenies". In general I find the author's criticisms valid when it comes to many of the breathless claims of fans of DL's, but disagree with his conclusion that since it can't be proven that DL's are more productive that they aren't.
I have no empirical evidence to add to this debate, but lack of evidence is not a counter-example. That is to say, while the DL weenies may not have empirical evidence that DL's are more productive than statically typed languages, there is also no counter evidence demonstrating they are wrong. However there is a large body of anecdotal evidence that seems to support their position.
I'll add my own anecdote as I think it's quite expository:
I had been programming almost exclusively in C for over a decade when I undertook a task of writing a custom instant messaging system for an employer (this was in the 90's and there wasn't the plethora of IM software and protocols that there are today, plus they had specific requirements regarding logging, encryption, etc). The task seemed interesting so another employee and myself undertook to write the system using C. A week into the project, we'd managed to hack out a protocol, some low-level libraries and began work on server process. At this point we began getting bogged down. Neither of us had done much network-specific programming at such a low level and the details of process management were a real problem.
At some point I recalled a Linux Journal article about Python I'd seen a year or so prior. Out of curiosity, I decided to start a side project mirroring our system using Python rather than C to see if there were any benefits to be had.
This idea turned out to be a miserable failure. Within two days I'd finished my server process, implemented our required feature set, had a basic client GUI, written some stress tests and was starting to add new features. I showed this to my colleague. We immediately abandoned the C version and continued work on the Python version. At leat some of this was due to Python having better libraries than my C compiler, but the fact is, I mostly wrote low-level code, so I would attribute most of the productivity to Python's language features rather than libraries.
Now I want to reiterate: a decade of C experience. Zero Python experience. Also, I prided myself on my C skills. I'd written things like a cross-platform GUI (widgets and window manager) and a 3D surface modeler in the past. I had absolutely no problems with C. In fact I loved it. But I couldn't deny how productive I'd become almost overnight with Python.
I also want to nitpick one more little bit from the article. The author states:
As an aside, let me point out that the removal of explicit typing is not without its disadvantages, even though it may reduce code volume to some extent. Consider that when you remove type qualification from the source code, you're also removing some documentation of your intent. Given the paucity of documentation in many code bases, it seems unwise to start removing type-related documentation as well. Consider also — if it's good form to give your identifiers meaningful names to aid in comprehension, isn't it equally good form to explicitly assign them types, for exactly the same reason?
First of all, the author badly confuses "type" with "static". Python has types. Further, they are explicit. Consider, for example:
x = 6
Is that not explicit? 6 is clearly an integer. Do I need to spell it out? Well in some languages you do, but I don't think that it necessarily makes it any more explicit. Is the following really any clearer?:
int x; x = 6;
If you must spell everything out, then why not:
var x = int 6
I'll tell you why: because there's a difference between explicit and redundant. The assignment makes the type abundantly clear. All the type declaration does is add a useless line of code that helps no one except the compiler.
Frankly, if you think the word "int" adds any clarification to your intent, then you are badly deluded. If you have read a section of code to determine the purpose of a variable and are still unsure of its type, then no amount of documentation is going to help you.
"Sure," I hear you say, "but I'm not referring to scalar types, but user-defined types, such as records." The same argument holds for more complex types as well. Let's have some real code to see how Python is a bit more terse than C:
class Person ( object ):
def __init__ ( self, name, email ):
self.name = name
self.email = email
p = Person ( 'John Doe', 'john@jdoe.com' )
Now in C:
typedef struct Person {
char *name;
char *email;
} *personPtr;
personPtr create_person ( char *name, char *email ) {
personPtr;
p = ( personPtr ) malloc ( sizeof ( struct Person ) );
p->name = malloc ( strlen ( name ) );
p->email = malloc ( strlen ( email ) );
strcpy ( name, p->name );
strcpy ( email, p->email );
return p;
}
void destroy_person ( personPtr *p ) {
free ( *p->name );
free ( *p->email );
free ( *p );
*p = NULL;
}
personPtr p;
p = create_person ( 'John Doe', 'john@jdoe.com' );
destroy_person ( &p );
It's been a while since I've done much C and I don't feel like testing the above, so please forgive any errors.
You might think that the C example is a bit overkill, but you're wrong. If you think about how such code might be used in a real application, you'll quickly realize those two pieces of code are functionally equivalent. They both allow for an arbitrary number of instances of Person records, and both allow for arbitrary length of name and email.
Finally I'm going to call "foul" when proponents of statically-typed languages claim that explicit type declarations (I should call them "separate" rather than "explicit", but whatever) buy any sort of help when it comes to debugging. Write very much C and you'll soon find that your most flexible code is filled with void pointers. A linked list of arbitrary structures? void pointers. Almost all the interesting code I wrote in C involved void pointers and type casting to a large degree and frankly that's the main thing dynamic languages do for you: they encapsulate and provide support for using arbitrary objects without the nonsense of declaring a type that you aren't going to use anyway.
I'll grant that C is hardly the epitome of statically-typed languages, but it's what I'm most familiar with and makes a striking example of how static typing leads to overly verbose and redundant code.







This is one of the reasons I really like Haskell. It still has static typing, but the annotations are optional and typically can usually be omitted in favor of allowing the compiler to infer the type from the context.
Not only does this eliminate redundant declarations of type information but it also allows one function to operate on sets of types.