Learning Clojure(Script)

Since I discovered the famous and magnificent SICP book and lectures many years ago I have been fascinated with the elegance and beauty of the Lisp dialects. I have never used Lisp for anything significant, but I have dabbled a bit with GNU Guile and hacked some fun things for the Gimp back when Scheme was the only extension language.

Recently I met Rasmus Erik of Solsort.com who told me about ClojureScript and that it is possible to use this variant of Clojure to create modern web apps. Exciting! A possibility to build things for the world in a real Lisp!

Clojure and ClojureScript

Clojure is a modernised Lisp dialect made with concurrency in mind and implemented for several platforms including the CLR and the JVM. As far as I can tell the primary platform is the JVM. The Overview section on the Clojure home page gives a good intro to the language features.

To write a web app with ClojureScript Clojure programs are compiled into Google Closure Compiler compatible Javascript. The Clojure semantics are preserved but there are notable differences to Clojure running on the JVM. A good (complete?) overview of these differences can be found in the ClojureScript Wiki.

Learning the Language

There is a good overview of ClojureScript basics in the Light Table ClojureScript Tutorial, including functions, variables, iteration and how to use the basic parts that are needed to start writing simple programs in Clojure. The Reference also gives a good overview. Reading these was good starting point for getting into the basics. I am curious to find out what I can do with the features that are more exotic to me such as macros, multimethods, protocols and types.

For a hands on tour of the language features I started using the ClojureScript Koans which is an online version of the Clojure Koans for ClojureScript. These are nice and simple exercises that do not require too much. At least the first few of them, and that is as far as I got before I ran into a bug that made it impossible to submit any of my solutions… Boring. Oh well.

Luckily I came across 4Clojure which is a set of problems in different difficulty levels from elementary to hard. At the time of writing there are 156 problems and a total of 911791 problems solved. After solving a problem it is possible to see how the people you follow have solved the problems. This has turned out to be a great way of learning new and clever ways to approach a solution, so I now follow lots of people there to learn how to write better code. My solutions reveal that I still lack experience with the ways of the Clojure core API and am still quite imperative in my coding style.

To get help the REPL (doc ...) and (source ...) macros have proven to be an invaluable resource for getting a peek at what is going on under the hood. Other good learning resources I have used are the Introduction to Clojure and the Cheat Sheet for a good overview of commonly used functions.

Tooling

In the beginning I played around with the Clojure REPL by running the clojure command that my Linux came with out of the box, but there is a better option; or two better options: Leiningen and Boot. These are both build tools and handle all aspects of project automation, including starting a REPL specific to a project.

As far as I can tell Leiningen is the more mature and most used tool and Boot is planned to be a better engineered replacement for it. Leiningen takes a declarative approach for configuring a project in the project.clj file while Boot reads a program that describes the build process in the build.boot file.

The most important thing for me was to get up and running with a REPL so that I could run things from my editor in the program environment while still maintaining state. Getting the REPL up and running and having the browser reloading the files I changed on write, while maintaining state was not a problem with either Boot or Leiningen, but I cannot say that I have had consistent success with an editor connection to the REPL.

Being a Vim user I Followed the Clojure with Vim and fireplace.vim guidelines and installed fireplace.vim to connect Vim to a running REPL and vim-clojure-static for Clojure syntax highlighting and indentation. It is very nice that the latter plugin is easily configurable so I can customize what I would like my code to look like.

For some reason Fireplace.vim throws an exception when evaluating code that I have not yet found a solution for. I used quite a lot of time trying to get this to work well and even started trying to use Spacemacs for a while.

I’m not yet comfortable enough with Emacs and after also having REPL connection problems in Spacemacs I decided to go back to plain Vim. Eventually I will go in for another fight with lein figwheel and Vim. I’m possibly just a noob since it seems other people are using Fireplace.vim without issues.

Html5 Single Page Apps

To get started with with apps I started following the Modern ClojureScript tutorial. This tutorial exists in two versions: a first edition using Leiningen and a modern version that uses the Boot build tool. I immediately started with the second edition to get to know Boot. I had used the lein command before and if everyone is going to switch to boot shortly it would be a good idea not to use too much time getting to know a deprecated system. At least that was what I thought. I now have the impression that it is a good thing to use Leiningen for a while still.

Anyway. I have not yet completed Modern CLJS tutorial but I have the impression that it gives a good hands on overview of how to develop a simple non-framework web application using Clojure for the server and frontend. The tutorial includes what looks like an extensive section about how to test applications and I would like to revisit that at a later point.

Reactive Apps

I then had a look at two frameworks, Om and re-frame. Both build on React and provide a very high level abstraction for building apps. Om seems to have quite a large amount of documentation and tutorials on the Om Wiki plus it is being developed by David Nolen one of the active people working on ClojureScript, so it is probably interesting to follow.

The re-frame framework builds on top of another framework that wraps React, the Reagent project. It provides an even higher level of abstraction and implements some of the ideas of functional reactive programming as implemented in the Elm language. Also, it may be likely that some ideas in re-frame contributed to the creation of Redux. The immutable ways of Clojure seem to be a very good fit to this programming model.

I have chosen to look more deeply into re-frame and building a smaller app using some of the pre-made components from the re-com library. I am curious to see how it goes.

So, no more Javascript?

Having written quite a bit of Javascript and looking appreciatively to many of the new and juicy ES6 features it initially felt like a sacrament sacrilege, to have a compiler spit out obfuscated JS to be consumed by some VM. Ack! The injustice! So, I am still not in a position where I feel that I can write better programs with ClojureScript, mainly due to lack of experience. However, the elegance of the language still has me fascinated and I anticipate a future may come where I will write more Clojure and possibly less Javascript and other curly-braced languages.

As it is now, I have some problems with ClojureScript:

It is really slow to get up and running. Part of the time I have been working on a Chrome book with not so much power and it sometimes took up to a minute to get the REPL running. Also building on file save is not as fast as I expected and being used to INotify based tools from Node and Linux this was not very exciting. Also the way I start the REPL as described here requires running lein repl and pasting a couple of lines of code into the REPL to get a connection to the browser. There probably is a better way.

The ClojureScript incompatibilities to Clojure have also been a source of frustration for me and I assume many of them will remain due to the nature of the browser.

Also, I worry that debugging stack traces from code that is in production will be more troublesome since the actual problem has to be sought with a combination of a stack trace from an arbitrary browser and a source map to find out what actually went wrong. This is probably possible, but much easier with plain Javascript.

On the plus side this is a real Lisp, modernized, even. And the Clojure and ClojureScript communities seem to be very alive with many new developments. So I am excited to get to know Clojure better.