Below are some of my thoughts about working in Clojure so far. I’m still really new to this language (and lisps in general) so I can definitely see myself changing my mind on some of these criticisms as I learn more. So far my overall impression is that compared to other functional languages, I’m not really getting anything extra with Clojure when it comes to expressiveness or maintainability.
1. When it comes to writing code, the parentheses are really easy to get used to.
I already have some experience with other functional languages, so I felt like I didn’t really have to change my thinking much to have it fit in with Clojure’s way of doing things. I get that the uniform syntax opens up the door for easier metaprogramming but for normal use I still prefer inline syntax to (having (to (nest (everything)))). But overall it doesn’t really seem to slow you down when you’re writing code.
2. When it comes to reading code, the parentheses make things harder to understand.
So here’s an example of some sample code I was writing (full code here):
Just in this simple function we’re nesting once at the letfn, then again at the let, then again at the if, then again at the other let, and then finally again at the doseq. Other languages would have similar levels of nesting for this kind of function but the difference is that you wouldn’t have to think about it as much. I feel like the parentheses are forcing me to think of the AST of the program and that’s distracting when I’m just trying to read and understand the code.
3. Clojure has good error messages.
There are a lot of different places where things can go wrong in Clojure. You have byte code compilation, you have macros expanding, you have Java interop, and you have an interactive environment that may or may not be in sync with the rest of your code. So I think it’s really impressive how helpful the error messages and stack traces have been so far. Even though Clojure’s not a widely used language doing Googling the error message usually helped my sort out my problems right away. I know that one of the design goals of Clojure to be as practical as possible and I think that’s something that really shines through in this case.
4. One-off command line apps are not a good fit for interactive development.
I feel like I haven’t really done a good job for getting a feel of coding with the REPL. The kind of test applications I’ve been making so far are all standalone utilities that you can compile ahead of time and call from the console. I think Clojure environments are just meant to stay running continuously (and starting them up can be really slow…). So I think I need to find myself a better test project work on.
One other thing related to this that I didn’t get a chance to look into yet is finding a good way to debug Clojure. Being able to inspect your current definitions is fine, but sometimes it’s still helpful to know what’s going on at every step of execution. I was relying on the “stick print lines everywhere” method of debugging and I feel like there’s probably a better way things than that.
5. I haven’t gotten to the good stuff yet.
There are two language features that I haven’t tried out yet: macros and mutlimethods. These are things that other (non-lisp) languages don’t have, so I’m looking forward to checking them out. I also haven’t done much with the asynchronous features either, so I also want to take a look at those. So far though from what I’ve seen, I feel like in terms of capability Clojure’s not really that distinguishable from the crop of functional languages that’s currently out there but maybe these other features will change my mind.