Diving into ClojureScript Aug 9, 2017

In my post on multi-platform development recently, I mentioned Clojure (CLJ) as one of the languages which can be compiled to JavaScript - then it’s called ClojureScript (CLJS), although they are almost identical.

Having spent a fair amount of time recently reading half a dozen books, viewing tens of tutorial & conference videos, and scanning hundreds of web pages, I’ve been massively impressed by its concepts as well as its implementation - not only of the language itself, but especially the Reagent wrapper around ReactJS and the Re-frame library.

My take on it, in one word: Revolutionary!

Web front ends will never ever be the same again now that React has introduced uni-directional data flow and the virtual DOM. This is not a hype, it’s the logical next step for UI apps, after Model-View-Controller and various more recent “MV*” variants.

Even Angular 2 has gone through a total re-design and now uses The React Approach.

Reagent wraps React, ends up as less code and will often be faster. Hard to believe, but true (hint: immutable data structures and Google’s Closure optimising compiler).

Re-frame closes the loop. Literally: it offers a set of conventions for dealing with events (user, network, time, whatever) and leads to a very clean structure for the entire app.

For apps with a lot of client-side data, there is also the DataScript package, based on the Datalog declarative programming language. Think of it as SQL plus Prolog, reloaded…

LISP

Clojure is a dialect of Lisp, also known as “Little Irritating Single Parentheses”. While I used to hate that notation, with Parinfer support in my editor, I’ve come to love it. The notation exists for a profound reason.

FP

Clojure also adopts many concepts from functional programming languages such as Haskell, Erlang, and Elm. Unfortunately, wrapping your mind around “pure” FP requires understanding monads. I gave up many years ago - and never saw the point of data structures which can’t be changed.

Until Clojure, which brings back mutability in a very controlled manner, in the form of special “atoms” (and suprisingly close to variables + arrays in the Tcl language).

But why?

Why not go with the flow, i.e. JavaScript or some variant, and build web applications that way? Why add an extra compilation layer on top, which produces JS anyway?

Won’t you have to learn all the underlying JavaScript, React, HTML, DOM, CSS anyway? Won’t errors just get buried in layers of strange stack traces?

To start with the latter: NO. Reagent wraps React and the DOM to such an extent that I can ignore them. ClojureScripts “hiccup” notation replaces HTML layout, with the same notation as the rest of the code. And YES, you still have to know how browser events “bubble up” and the many details of CSS, but IMO there’s no way to avoid that.

Most (not all) errors generate nice on-page warnings w/ CLJS code and line numbers. With DevTools, data structures are shown in CLJS format in the JavaScript console.

Choosing a programming setup is hard - I’ve tried JS (and NodeJS), and “npm”, and “grunt”, and “gulp”, and “bower”, as well as YeoMan, WebPack, Uglify, and everything else you get with that big ecosystem, and development just kept getting more and more unwieldy. I tried Knockout, Angular, and JS-based React - again: they and their tools (with never-ending updates) just didn’t do it for me: Tooling Overload!

On the server side, Go now replaces 95% of C/C++ for me. On the client side, i.e. the browser, it’s not as easy - some tooling is always going to be needed, and Leiningen is not perfect. But it does its job well. A single “lein new re-frame myapp” command pulls in all the dependencies, and it won’t break when any of those get updated.

It’s been a steep learning curve - maybe you can benefit from some of my explorations via this repository, where I try out various starter templates and packages - gradually settling on Leiningen, Figwheel, Reagent, Re-frame, and Devcards as my choices.

An example: SVG

I’ve been doodling and slugging my way through all things CLJS lately, and created a minimal example for rendering a simple graph to SVG in the browser. It’s not a one-way rendering, it has draggable objects:

For a live demo, go here. There’s no server, it’s an index.html plus an app.js file, and runs in your browser, the code on GitHub. The entire source code is about 70 lines. While it does not do this approach justice, it’s a tiny demo of just three small text files.

My web development setup is as follows:

An editor sits on the left. The top middle window is running “lein figwheel”, which does live reloading without losing app state (more on that in a moment). The top right window is a spare shell, always in view. And lastly, the big yellow window is Google Chrome, with its developer console.

Live reload

Live reloading has become quite popular, but with Reagent, it’s not what you think.

When I change code in the editor and save it (or switch tabs / focus), Figwheel will inject the modified code into the running application, without affecting its state. In the SVG demo, I can drag an object around, reload new code, and see the new effects while the objects retain their new position.

This. Is. Huge. … Say you have the app scrolled to a certain spot, adjusted some settings, tried out a new function, and it doesn’t work. Without live reload, you have to rebuild/refresh the browser (which can be automated), but then the app is back at its starting point. With Figwheel’s live reload, you get a little notification on the page, and that’s it: Coding As It Should Be.

It’s as if you’re editing the live application (Tcl developers have this as well, but it’s much more complete in ClojureScript).

My world: Forth + C + Go + ClojureScript!

Now if you excuse me, I must go back to my dev setup and work on JET’s new front end.

Weblog © Jean-Claude Wippler. Generated by Hugo.