For the past couple of years, I have tried to learn and evaluate one new programming language each year. One nice way I've found is by solving the Advent of Code puzzles.
Learning a new language by solving those puzzles has a few notable benefits:
- A nice 25 day streak, so that you can build a habit.
- Small and self contained, usually solved in 30-60 minutes without needing to bring in any dependencies.
- You get to exercise the standard library and built-in data structures a lot.
- You get to implement some well-known algorithms (e.g. A*, depth- or breadth-first tree search, graph walking etc.)
- You get a feel of the performance characteristics, since some puzzles require some intense calculations.
- You can read other solutions in your language of choice in order to learn new tricks.
- It's fun!
In 2016, I tried Elixir. For 2017, it was Clojure. In both cases, I've started a couple of weeks in advance by actually learning the language and libraries, solving older puzzles, so I can be ready on December 1st for the new puzzles.
Here is a rough list of my takeaways, after two solid months of daily Clojure puzzle-solving:
- It took me roughly two weeks to get used to the
(parentheses). I don't notice them any more.
- The Clojure community is very friendly and very experienced.
- It helps to have some functional programming experience before trying Clojure. In my case, Elixir had many many similarities so at times I felt like just learning a new syntax, rather than a new way of programming.
- Clojure is fast, even when using the functional and immutable data structures. If you need to go faster, you can drop down to the transient versions, to the Java collections, to the unboxed math operations.
- Clojure is flexible. You get immutability by default, but if an algorithm is better expressed by having a mutable data structure you can also have that.
- Having a REPL that is integrated with your editor (in my case, Spacemacs + CIDER) is eye-opening. I will try and make a screencast or stream of what this looks like when solving those puzzles — it's really hard to put into writing, but it makes other REPLs seem downright primitive.
- The Clojure documentation can be hard to decipher, and the
clojure.corenamespace is huge. ClojureDocs helps, but I believe there's a need for an
apropos-like functionality built into the system.
- In the first couple of weeks, the error messages where a bit cryptic. They still are, but now I can decipher the common ones. Doing incremental work with a REPL-connected editor mitigates this somewhat. Also, CIDER has a built-in debugger that's very easy to use and has saved me from littering my code with
- Java is huge, and the JVM is powerful. I haven't touched the ecosystem since 2007, and I remember now why most enterprise software is written in Java: There's a robust library for pretty much everything you want to do. Being able to explore and use those libraries from a higher-level language is very very interesting and unlocks a huge amount of potential. Even the JDK itself has a great standard library and can do pretty much everything.
- Reading other people's code can be either an enlightening experience or an exercise in frustration. This doesn't seem to be dependant on the author of the code, but rather on whether they are using the same 80% of the language you are using. To be fair, most people that are solving those puzzles are not aiming for readability or maintainability.
In the end, my verdict on Clojure is whole-heartedly positive. However, the next avenue I want to explore is actually ClojureScript, both on client side (probably via re-frame), but also on server side (on Node.js).
In case anyone is interested, you can find my 2017 solutions on GitHub. You can also find a community-curated list of Advent of Code solutions in Clojure. Finally, a special mention to Mike Fikes's solutions that are in cross-platform Clojure and ClojureScript.