Clojure compiled to JS
A Introduction
@friemens
Agenda
Some general remarks (a.k.a „blah-blah“)
Getting started with the tooling
Exploring the language and core library
React / Om / core.async
Wrap up
Powerful core library
Why?
Functional programming
One language in backend and frontend
Unfamiliar tooling
Why not?
Too much for quick-and-dirty UI enhancements
An alien language
Sweet spot: full stack Clojure
ClojureScript
Clojure
Datomic
„Rich-Client“
in a browser
Backend
Database
Fundamentals
(a.k.a things-we-need-to-understand-first)
It's a Lisp (OMG!)
The core idea of Functional Programming™
A hosted language
Lispy syntax
Ordered
Associative
Function
Invocation
var x = [1,2,3];(def x [1 2 3])
(def m {:a “Foo“}) var m = {a: “Foo“};
function bar (a) {
return a + 42;
}
(defn bar [a]
(+ a 42))
bar(0);(bar 0)
The REPL*
Read-Eval-Print-Loop
*
Pure functions
Side effects
Context
The core idea of Functional Programming
Thou shalt not mutate in place
Mutability causes cognitive load
var x = [1,2,3];
foo(x);
After foo,
what's in x?
ClojureScript is built on immutability
(def x [1 2 3])
(foo x)
(assert (= x [1 2 3]))
… on efficient immutability
Structural
sharing
x x'
ClojureScript is a hosted language
Your host: the browser
Clojure Script
Getting started with the tooling
Ideal tooling
Browser
Console
Editor
REPL
Instant feedback
Highly recommended tutorial:
https://github.com/clojure/clojurescript/wiki/Quick-Start
cljs.jar
Or follow the steps on
https://github.com/adzerk-oss/boot-cljs-example
Getting started with Boot
Either use the example from
https://github.com/friemen/cugb/tree/master/cljsintro
Traditional architecture of UIs
View
Model Controller
Dataflow approach to UI
Om / React
core.async
App. State View
Databinding
App
state
DOM
event
updates
mutations
Controller
e.g. Angular
transform
render
diff + merge
DOM
App
state
swap
React+Om
Virtual DOM
event
DOM operations are
soooo sloooow.
Bi-directional
Uni-directional
Burn Hollywood Burn!*
Public Enemy (1990)
*
Callbacks are ok, but, uhm ...
function reloadAddressbook (state, event) {
ask("Are you sure?", function (answer) {
if (answer) {
ajax.get("/addresses", function (response) {
if (response.statusCode == 200) {
state.addresses.items = response.body;
}
});
}
});
}
Ask for confirmation
ok?
Issue GET request
success?
Replace items
But how do you implement concurrent requests?
CSP* with core.async = channels + go blocks
Communicating Sequential Processes, Tony Hoare (1978)
*
(def c1 (chan))
(go-loop [xs []]
(let [x (<! c1)]
(println "Got" x ", xs so far:" xs)
(recur (conj xs x))))
(put! c1 "foo")
;; outputs: Got bar , xs so far: [foo]
a blocking read
make a new channelcreates a
lightweight
process
async write
core.async: no need for callbacks
Ask for confirmation
ok?
Issue GET request
success?
Replace items
(defn <addressbook-reload
[state event]
(go (if (= :ok (<! (<ask "Are you sure?")))
(let [{s :status addresses :body}
(<! (http/get "/addresses"))]
(if (= 200 s)
(assoc-in state
[:addresses :items]
addresses)
state)))
Getting started with
React / Om / core.async
Wrap up
ClojureScript is ...
... overkill for little enhancements
… a mature language to tackle UI complexity
… demanding to learn, but this will pay-of
Links to resources on GitHub
https://github.com/friemen/cugb/
Thank you for listening!
Questions?
@friemens riemenschneider@doctronic.de

ClojureScript Introduction