You are here

Why static typechecking is your friend

I have just finished a little 120-line Nickle program. The purpose of the program is quite simple: given a list of lecture titles and topics as a CSV file, I need to format a schedule, with the proper dates, as HTML for my syllabus page and as a CSV import for the Sakai-based portal I'm trying out for my course this quarter. Nickle is good at this kind of thing, as it turns out, in spite of not really being about text processing or traditional scripting.

Anyway, the interesting part to me is the development process I've developed for Nickle code. Basically, I start typing the code into a text editor. At a convenient stopping place, I run Nickle on the code just to get the static checks. When my partial program is free of syntax and type errors, I type some more. Eventually I run and debug in the usual way...

Note that I always get syntax and type errors when I check. Maybe I'm just an unusually bad programmer, although I don't think so. (Yes, this is a blog topic in itself, and I'll get there some day soon.) What I think is that human beings are naturally prone to this sort of mistake. The key point here is that it's way better to catch these bugs at compile time than at runtime.

In this particular program, I accidentally scoped out an integer counter named line with a string buffer named line containing the contents of the line. In this case, it would have definitely always caused a runtime error in a dynamically typed language such as Python, but I wouldn't have got there until I had written a lot more code: all my debugging context would be gone, and I would be facing a bunch of these kinds of runtime errors at once. Note that if line was referenced only in exceptional cases, you'd have a subtle bug that would cause the code to crash at an unsuspecting user who would probably have no idea how to fix it.

I also had some bad bugs in date generation, that the static analysis utterly failed to catch. Static typing is not a panacea. However, in Nickle it's practically free; by design it never gets in your way by whining at you when it shouldn't, and if you don't like it you can selectively turn it off by using the poly type wherever you feel like it. Everything's still typechecked at runtime by a more restrictive system, so in the worse case you're back to the Python situation.

Immediate future work for Nickle includes dramatically decreasing the runtime typechecking cost of Nickle programs through a clever trick we've figured out. But that cost will never entirely go away. The next piece of performance work will be to use the static checks to eliminate some runtime checks: with a little work, we can ensure that not only do statically typed Nickle programs run safer, they run faster.

The biggest problem with Nickle's type system is its current lack of a way to give good static types to ADTs, especially ADTs for containers. We'd like to do parametric polymorphism or something like it, but haven't figured out just how to make it work happily yet. Once that's done, we'll be able to routinely have the best of both worlds: programs that are statically checked when they can be, and dynamically checked the rest of the time.

In my experience most of the people who whine about the problems of static typechecking are thinking of old-school languages with restrictive and annoying static type systems. The functional programming language community has decided that static typing is awesome, and has gone to a lot of work to make it better. Even C++ has some decent static typing stuff now, although it isn't my ideal.

IMHO there's no reason that scripting languages shouldn't also have static typing. I hope that Python and friends emulate Nickle in this regard sometime soon.