Thursday, October 19, 2006
  Would you like a side of referential transparency with your order of static typing?
Recapitulating some of the arguments for and against static typing has been very refreshing. And thanks to everyone who took the time to share their point of view.

Leaving aside the argument that static typing helps your IDE help you, the really big idea behind modern static typing is that because certain properties of variables are invariant, it is tractable to perform a lot of analysis on a program looking for contradictions. For example, we say that foo is an Integer, and then a little later on we call foo.append . Since Integers don’t implement a method for appending, we know that there is an error in the program without having to run the program.
Thoſe who would give up Essential Liberty to purchaſe a little Temporary Safety, deſerve neither Liberty nor Safety.
Benjamin Franklin

And do you know what? Although I accept that this is true, and even useful, I haven’t personally been swayed by it (I’m just going to give my experience here, not a prescription or advice to others). The problem, as I see it, is that the statically typed languages I’ve used for production work have had such primitive typing systems that I couldn’t use them to solve really important problems.

Errors where I mistakingly try to call append on a String when I should be calling it on a StringBuffer just don’t make up for all the extra verbiage and the onerous restrictions on meta-programming imposed by popular languages.

Cognitive Hazard

But I had a sudden “Oho, you’re busted!” moment a few days ago. Didn’t I write a nice post explaining why mutable local variables are bad? The gist of my argument was… wait for it… mutable things make it hard to move stuff around, because you don’t have those nice invariants to reason about. Hmmm. Could there be a strong parallel between getting rid of mutable variables and static typing?

Static typing and stateless programming

Yes, of course there is. It’s about minimizing the state changes. Static typing is about having just one state for each variable’s type. Programming with immutable variables is about having just one value for each variable. I advocate the latter. Why haven’t I embraced the former?

Well… I could argue that dynamic meta-programming is worth more to me than the benefits of static typing. They really are worth a lot more than the benefits of the simplistic typing systems you find in popular languages. But are they worth more than the powerful systems in languages like Haskell or ML? Maybe not.

And how dynamic is my meta-programming? I love the fact that I can use constructs like acts_as_versioned in Ruby, but there are languages that allow static meta-programming (like Scheme’s macros) that would go as far for much of what I do. Much farther than the restrictive straight-jacket of popular languages, anyways.

Paradigm smells

This brings me to writing DSLs in Ruby. One of the reasons DSLs are incredibly useful is that they are declarative: The what is cleanly separated from the how. Lots of successful DSLs are “business rules”, they aren’t statements to be executed, they’re constraints on the behaviour of a system. Just like static types are constraints.

Does this sounds familiar? I’m confessing that one of the reasons I like Ruby is that it’s easy to write things that are static, that don’t change state. But Ruby is all about having flexible things that change at runtime. This is what you might call a paradigm smell, the paradigm of the language—types change on the fly—is at odds with the kind of programs I try to write in Ruby.

Isn’t that interesting?

p.s. Okay, all of you static typing fans who are rolling up your sleeves to write an “I told you so” comment: before you hit “publish,” ...

Are you curious about what would happen if you turned the static typing knob up to eleven? If you took the Red Pill? Could you use a really powerfully typed language to detect XSS vulnerabilities in the compiler? Could you switch from an impertitive, loop programming style to a functional style and get rid of mutable variables? Could you express your domain logic declaratively in a DSL instead of in procedures and methods? If a little compile-time analysis is good, how much better could a lot of compile-time analysis be?

Comments on “Would you like a side of referential transparency with your order of static typing?:
I don't have enough experience with enough varied languages to weigh in on either side of this debate.

But I do have one question. If capitulate means to give in, and you start this post by recapitulating, are you giving in?
I'm ready to take the red pill, but I'm not sure I'd want to train my team to modern type systems (even if we used to parctice prolog, Curry, Clean or Mercury are far more complex), moreover given the error reporting problem they induce.

Even introducing java 5, "extends", "super" and type inference (yes, there is in java) is a difficult training problem.

One other side of the matter (you already blogged about it) is the cost of entry to Haskell/ML jobs to actually practice in a ML-oriented company before bringing the thing to a "normal" company. You need to own a PhD to get a position, and well, I don't.
You know, it amazes me that ostensibly smart people like Raganwald, Steve Yegge, etc. don't "get" the main benefit of things like static typing and refactoring IDE's.

The main benefit is not about preventing runtime errors. (Although it can, on occasion, assist with that.) The benefit is speed and efficiency while editing code, and, consequently a shorter write-compile-test cycle.

It's incredibly useful to me to be able find out immediately FROM MY EDITOR that I made a typo, or passed an invalid parameter, or some such, rather than having to wait to compile and run my code before I find out. This may not sound like much benefit, but multiplied across the hundreds of times a day that I make code changes, it's a huge time savings.

Automated refactorings in the IDE are a similar efficiency. Being able to quickly change the name of a class or method - or even move it to a new package - while having all the housekeeping of updating references get done automatically(!) is a huge time savings. Things like this let me as a developer focus on "the big picture" (e.g., rename this class) without having to concern myself with the tedious, repetitive, nitty-gritty details of actually carrying out the myriad individual editing changes needed for the operation.

These capabilities available to me at editing time as a result of static typing are a huge boon to my productivity - certainly an order of magnitude increase at least.

So enough with the "static typing doesn't prevent errors" straw man argument. "It's about the coding, stupid!"
You know, it amazes me that ostensibly smart people like Raganwald, Steve Yegge, …

Steve has his own soapbox. Please stick to critiquing my thoughts here. I would hate for someone to say “Hey Steve, you and Reg both believe X, and he said such-and-such about that, and he’s wrong, therefore, you’re a Putz.”

That wouldn’t be fair to him, now would it? For a more concrete example, he does seem fairly smart, whereas I do not. So perhaps the “ostensibly” thing applies to me, but he is unfairly tarnished by my reputation?

Anyways, I have a question for you. I wrote something right at the top of the post:

Leaving aside the argument that static typing helps your IDE help you

So… what part of the words “leaving aside” were unclear? I didn’t say that IDEs help you, but I didn’t say they didn’t. How do you know whether I love IDEs or hate them or feel indifferent?

In this post, I don’t say anything one way or the other about IDEs.

You say that “static typing helps prevent bugs” is a straw man argument. Please help me become a better writer: where did I go wrong explaining that I’m actually interested in investigating statically typed languages?

I absolutely, positively did not say that the only benefit of static typing is preventing bugs, and since it doesn’t do that, it is no damn good. In fact I linked to a post where someone uses a good static type system to solve an important problem!
There's definitely something weird going on here, I agree. But I think it is partly that, as others have put it, Ruby doesn't get in the way. It isn't purely functional, and that makes some things easier that make learning Haskell more difficult. It allows functional and declarative styles where that makes sense. And the DSLs are not entirely declarative either, for that matter.

The "trouble" with static typing, I think, is the amount of keyboarding, even with automatic completion, when coding. So "It's the coding, Stupid" is incomplete. Also, this type information gets in the way when trying to read code. There are things I'd like a Ruby IDE to do, which it cannot. So Ruby isn't perfect either.
But we know there's no silver bullet. I suspect we just don't yet know why there isn't.

For myself, I'd like to understand functional programming much better than I do. I thereby admit a certain level of ignorance in this debate!
In Haskell you don't have to type the types in code because they can be inferred.
@Anonymous, what you fail to notice is that all those fancy refactoring features you're talking about, are not the result of static typing, they were stolen from Smalltalk, a dynamic language. It's just that in a dead system based on files, you need static typing to implement refactoring, not so in a runtime system like Smalltalk.

All you static language fans need to stop pretending that you invented the IDE and refactoring and acknowledge that all that shit came from Smalltalk, which is still a vastly superior environment to work in, and still dynamic.

The trouble with static typing isn't how much you have to type, it's that no type system exists which can prove all valid programs. They all suck to some degree, some much less than others, and prevent you from doing things which would otherwise work were it not for the type system.

What you say about Smalltalk's history is true, although a tad abrasively put :-)

That being said, the fact that type systems cannot prove program correctness in theory doesn't mean they don't have value in practice.

To put the point to the ridiculous extreme, we cannot prove that programs do not halt in theory, but that doesn't stop us from running them in practice.

So we can hold out hope for a type system that, whilst incomplete in theory, is useful in practice.

<< Home
Reg Braithwaite

Recent Writing
Homoiconic Technical Writing / raganwald.posterous.com

What I‘ve Learned From Failure / Kestrels, Quirky Birds, and Hopeless Egocentricity

rewrite_rails / andand / unfold.rb / string_to_proc.rb / dsl_and_let.rb / comprehension.rb / lazy_lists.rb

IS-STRICTLY-EQUIVALENT-TO-A / Spaghetti-Western Coding / Golf is a good program spoiled / Programming conventions as signals / Not all functions should be object methods

The Not So Big Software Design / Writing programs for people to read / Why Why Functional Programming Matters Matters / But Y would I want to do a thing like this?

The single most important thing you must do to improve your programming career / The Naïve Approach to Hiring People / No Disrespect / Take control of your interview / Three tips for getting a job through a recruiter / My favourite interview question

Exception Handling in Software Development / What if powerful languages and idioms only work for small teams? / Bricks / Which theory fits the evidence? / Still failing, still learning / What I’ve learned from failure

The unary ampersand in Ruby / (1..100).inject(&:+) / The challenge of teaching yourself a programming language / The significance of the meta-circular interpreter / Block-Structured Javascript / Haskell, Ruby and Infinity / Closures and Higher-Order Functions

Why Apple is more expensive than Amazon / Why we are the biggest obstacles to our own growth / Is software the documentation of business process mistakes? / We have lost control of the apparatus / What I’ve Learned From Sales I, II, III

The Narcissism of Small Code Differences / Billy Martin’s Technique for Managing his Manager / Three stories about The Tao / Programming Language Stories / Why You Need a Degree to Work For BigCo

06/04 / 07/04 / 08/04 / 09/04 / 10/04 / 11/04 / 12/04 / 01/05 / 02/05 / 03/05 / 04/05 / 06/05 / 07/05 / 08/05 / 09/05 / 10/05 / 11/05 / 01/06 / 02/06 / 03/06 / 04/06 / 05/06 / 06/06 / 07/06 / 08/06 / 09/06 / 10/06 / 11/06 / 12/06 / 01/07 / 02/07 / 03/07 / 04/07 / 05/07 / 06/07 / 07/07 / 08/07 / 09/07 / 10/07 / 11/07 / 12/07 / 01/08 / 02/08 / 03/08 / 04/08 / 05/08 / 06/08 / 07/08 /