It’s been a while since I did any browser-side programming. Even though I’ve been meaning to dive back into it for ages (the reasons for which will become clear in an upcoming weblog post). As we all know:
Browser + programming => JavaScript
While JavaScript is an amazing language, and also works impressively well on the server with NodeJS, I’ve never grown used to it. There’s only so much you can do before hitting callback hell, which evenpromises can’t really solve, IMO.
I’ve used CoffeeScript in the past, but that just alters the syntax, not the semantics of it all. One thing CoffeeScript did, however, was to promote the use of JavaScript as a “compile-to” language. And with it, support has grown in browsers to allow debugging while completely hiding the fact that the underlying browser language is still 100% standard JavaScript.
And so now, anno 2017, we have a wide variety of languages to choose from, which all compile to JavaScript and will run in virtually any modern browser.Terrific!
But languages aren’t everything - GUI programming requires a lot of effort and attention to detail. Properly supporting a rich user experience takes a lot of work!
I’ve tried to use Angular in the past, with mixed results: “NG” is a framework for building web applications, which creates a whole world (and terminology) to take care of the nitty gritty details. It’s also very opinionated - it’s either “NG’s way or the highway”, it seems. Which has been quite tedious at times, as NG kept on “evolving”.
Here’s how active Angular is on GitHub:
And then came React, aptly named since it uses reactive programming as its model.
React comes ridiculously close to a “view” model I’ve been working on for years in a previous life - which takes data as the starting point, and “renders” everything from there, including user interfaces and interactions. The difference is that React manages to solve all the issues I ran into.
Here’s how active the younger React is:
To understand React, all you need to get to grips with is this four-step diagram:
It looks deceptively simple (and it is, once the coin drops). There is one large pool of “state”. That’s where the mutable data of your application lives, including settings, and configuration. Even data entered in form fields and scroll positions if you want to be able to resume a page at that level.
From all that state, the application code decides what to show in the browser.
You can see it as visible = function(data)
, taken to extremes. There is
nothing “deep” going on: the code queries all the info it needs and comes up
with the DOM it wants to
present on the screen. No user involved.
Now the reactive part: when our user acts, we take the state, decide what this action means, and then apply appropriate changes to the state. Then the first process kicks in again, looks at the (new) state, generates a (new) DOM, and shows it on the screen.
That’s how React works, and that’s the programming model you need to develop for it. React’s brilliance lies in the fact that it does everything efficiently. Even though you can code in terms of re-generating an entire web page at every little click of the mouse, React does disruptively clever stuff to avoid doing redundant work. That’s the “Virtual DOM” stuff - it just works, ignore it.
The key benefit of React, is that it makes it easy to reason about what’s going on.
React can be used with JavaScript, and that’s in fact what it was designed for. But React made a major conceptual leap early on, when people realised that it’s a perfect match for functional programming and persistent data structures.
ClojureScript
Enter ClojureScript… a programming language in the Clojure family by Rich Hickey. It looks like Lisp, it’s functional, it will eat immutable data structures for breakfast, it compiles to JavaScript, and it supports live coding (just like Forth, yeay!).
If you’re not familiar withLisp orFP, it may not make much sense. Who wants stuff from decades ago? Parentheses … yuck! But there is one reason I’ve always kept an eye on ClojureScript: there’s a package calledReagent which brings everything together.
I’ve started exploring Reagent a bit more, to learn and to evaluate how it could work for what I have in mind for the JET project. My doodling can be foundhere. Some code:
(defonce app-state (r/atom {:count 0}))
(defn on-click []
(swap! app-state update-in [:count] inc))
(defn counter []
[:div
[:p "Current count: " (:count @app-state)]
[:button {:on-click on-click} "Increment"]])
(defcard-rg counter
[counter])
It’s easy to dismiss this as one more crazy programming language (or perhaps: yet another rabbit hole JC fell into), but don’t underestimate the concepts underneath such code. They merge HTML, React, and GUI programming into a singlecoherent programming approach, with some great development tools and conveniences.
As Rich Hickey once famously said in histalk: “Clojure rocks, JavaScript reaches”.
And that really nails it: JavaScript in the browser is now a given. But there is also a language which can go there while taking the programming side to a whole new level.
PS. Just to be 100% clear: this has nothing to do with Forth, which I’ll continue to use for development of all code on the µC side.