So I've been writing a lot of Clojure lately. Although I had a bit of Clojure experience before this project, and a lot more with Scheme and Racket, this was my first time using Clojure in a professional setting, and my first time in a long while using a language in the Lisp family for a truly substantial project.
nil. Look up a key in an identifier you thought was bound to a hashmap, but is actually a primitive or
But this isn't what I'm here to talk about today. Today, I'm here to talk about how the lack of static type system and the laxity of Clojure's dynamic type and
nil checking have affected my ability to write and debug code.
In a sentence... it really hasn't.
I thought the laissez faire approach to types was going to be extremely annoying when I first started working with Clojure. But now that I've been at it for a while, it really isn't. While I've made plenty of mistakes that would have been caught by static (and many dynamic) type checkers, have I truly lost as much time to them as I would have lost to writing boilerplate code in Java? Especially boilerplate code needed only to test a hypothesis while debugging that you have to write because the type system will only accept a certain class? And what about all the other bugs that crop up? I'm far from %100 sure, but I'm very skeptical that stricter type checking would make my life easier here — and it just might make it harder.
Furthermore, it's easy enough to validate data when you need to. In Clojure, this is usually accomplished using schemas, but you could easily write a domain-specific checker for a particular dataset if you needed it. I do validate data in Clojure when I need to, but it doesn't need to happen at every function or operator call and every identifier binding — and why create a class when a map will do the trick, without tying you to custom API? (This is a goal of Clojure.)
So, with all of that said and done: I still like static type systems. They have their place, and sometimes it helps to have certain mistakes caught at compile time. However, you can still write good code without them, and you don't necessarily lose much more time to type issues than you would in any other language. If you write decent tests, you'll catch those bugs either way.
(You're writing tests, right? ...right?)
Just make sure you validate user input and maintain decent test coverage, and you'll be fine, whether you're using a statically typed language or not.