pozorvlak: (Default)
pozorvlak ([personal profile] pozorvlak) wrote2008-03-30 08:40 pm

Pozorvlak's Conjectures

For the past couple of years (longer, actually), I've been thinking a lot about this business of static and dynamic typing in programming languages. Here's my current position on the matter.

Static and dynamic typing encourage and reward quite remarkably different approaches to the creation of software: everything from the nitty-gritty, (sit and think?)-edit-(compile?)-run-(test?)-(debug?)-(repeat?) cycle to the design (at all levels) of the software to be created, taking in every aspect of the tools and process used to support this design and implementation. Also, the choice of static or dynamic typing is best understood as part of a larger attitude towards development. Unfortunately, the use of a dynamic mindset with a static language not only means that you can't take advantage of the tools available (or even see why they'd be useful), it actively hinders success. The same is true for approaching a dynamic language with a static mindset.

I would therefore like to propose Pozorvlak's Conjectures:
  1. If you find that a modern dynamic type system causes more problems than it solves, you're probably doing it wrong.
  2. If you find that a modern static type system causes more problems than it solves, you're probably doing it wrong.
For instance, I find Haskell's type system causes me many more problems than it solves. Discussions with more expert Haskell users suggest that I am indeed doing it wrong. This guy, on the other hand, finds that "the dynamic languages stick out like sore thumbs because of the whole class of dynamic run time errors that show up that don't even appear in the statically typed languages". If you find this, I claim that it's because your code is not polymorphic enough1. You can get away with having code which only accepts data of very restricted types when the compiler does all the checks for you statically. When it doesn't, you're better off writing code that behaves well for a wider class of inputs, and dynamic languages give you much more facility to do this. Once you learn to code like this, your problems largely go away. As a bonus, your code becomes more flexible, and whole classes of techniques become possible that would have been literally unthinkable before. Similar claims, it appears, can be made for static languages: at the higher levels of mastery, one can use a static type system as a theorem-prover to establish some quite nontrivial properties of your program automatically and across the entire codebase. This allows for some excitingly different approaches to program development.

A corollary is that if you ever finding yourself saying that your port of Feature X to Language Y is better than the original Feature X solely because it's (statically|dynamically) typed and the original Feature X was the other one, you should probably save your breath. It will probably also be worth your while to go back and determine what advantages the opposite choice of typing regimen gave to Feature X's users.

1 A less interesting, but probably valid conjecture is that you're also not testing enough, or at least testing the wrong things. But this can't be the only answer. Dynamic programmers, in general, are not idiots; they are usually also Lazy, in the good sense. They're smart enough to work out that writing the equivalent isa_ok() test every time they would have written a type declaration in Java or whatever is no time-saver at all. Hence, they must need less type information overall for their code to be correct.

[identity profile] necaris.livejournal.com 2008-03-30 10:22 pm (UTC)(link)
Hmmm. Sounds extremely sensible, though I can't really say much from my own experiences as my statically-typed language knowledge is limited to C and C++ (plus, if you're generous enough to consider it a programming language, T-SQL).

[identity profile] totherme.livejournal.com 2008-03-31 10:24 am (UTC)(link)
All sounds pretty sensible to me :)

Further to you corollary, I'd note that making something (statically|dynamically) typed is a huge advantage if everything else in your system is going to be (statically|dynamically) typed. This is automatable going in the static->dynamic direction (just insert a bunch of runtime checks at the interfaces), but not necessarily the other way around (possible if the dynamic code happens to have been written in a pretty typey way to begin with - but if it was, then the author should probably have been using a static system in the first place. This is the subject of ongoing research by Smart People).

So, some obvious questions include "Is one style better for any clearly definable problem domain?" and the related "Why do people favour one style over the other?"

I think the first question is much harder to answer, and the second one potentially more interesting :)

[identity profile] st3v3.livejournal.com 2008-03-31 11:08 am (UTC)(link)
Found you via a second-order reddit link.

This has to be one of the best notes on S/D I've seen, basically because it transcends the two-ignorant-camps default answer.

My background is C#, but I'm playing with python and ruby and lisp for small stuff. My problem is that I can't see how to scale dynamic languages to big stuff. You're making me think I'm probably going to need a seriously different approach. Any advice on how to learn large-scale dynamic development?

Here's the kind of problem I'm worried about. I have a function I use throughout my codebase. Let's say I'm using python, and I've added a logMessage(msg) function. Now let's say I need to add an extra parameter (say, severity). How do I go about adding that parameter to every call? Static typing makes it easy. Is it possible to do in a dynamic language?

static v. dynamic: why choose?

[identity profile] maysonl.livejournal.com 2008-04-01 05:09 am (UTC)(link)
I'm currently engaged in a project attempting to get the best of both worlds – implementing Arc (or a significant fraction thereof), a very dynamic language, in Active Oberon, probably one of the most dynamic statically typed languages around: it separates interfaces from implementations quite nicely, allowing for multiple inheritance of interfaces in a basically single-inheritance object system. It also has very nice concurrency constructs - there's really sweet pipelined version of the Sieve of Eratosthenes in the appendices of the language report(and like any Wirthian language, its power/complexity ratio is very high).