clojure+clojurescript webapps
TRANSCRIPT
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)
Cross-Plattform Coding
#?(:clj (Clojure expression) :cljs (ClojureScript expression) :cljr (Clojure CLR expression))
(defn str->int [s] #?(:clj (java.lang.Integer/parseInt s) :cljs (js/parseInt s)))
Example
Reader Conditionals
Cross-Plattform Coding
#?(:clj (Clojure expression) :cljs (ClojureScript expression) :cljr (Clojure CLR expression))
(defn str->int [s] #?(:clj (java.lang.Integer/parseInt s) :cljs (js/parseInt s)))
Example
Reader Conditionals
Language features „a la carte“
core.logic
core.async
clojure.spec
core.match Haskell style pattern matching
Logic programming
CSP style programming
Schematizing data
overtone SuperCollider synthesizers
ClojureScriptCompiler
LeiningenBuild Tool
SassCompiler
nREPL
clojure.jar
Java Virtual Machine
Figwheel
CIDEREmacs
Tooling
Appstate
DOM
event
updates
mutations
Controller
e.g. Angular
transform
renderdiff + merge
DOM
Appstate
swap
React + Cljs Library
Virtual DOM
event
DOM operations are soooo sloooow.
It's not MVC as you know it
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?
callback 1
callback 2
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)))
Application Stateƒsubscription
ƒdispatch
ƒrender
BrowserDOM
Channel
ƒtransform
VirtualDOM
EventEvent
Current state
swap!
State
StateDOM
New state
Controller process
Big picture: uni-directional data flow
Remote Communication: De-/Serialization
> (def msg {:service :add-contact :payload {:firstname "Foo" :lastname "Bar"}})
> (pr-str msg);= "{:service :add-contact, :payload {:firstname \"Foo\", :lastname \"Bar\"}}"
> (clojure.edn/read-string "{:service :add-contact, :payload {:firstname \"Foo\", :lastname \"Bar\"}}");= {:service :add-contact :payload {:firstname "Foo" :lastname "Bar"}}
Pro tip: use Cognitects Transit
Serialization
Deserialization
Data
Data
Webapp Backend
Small libraries,no big frameworks!
HTTPserver
Middle-warefunctions
Routingfunction
Handlerfunctions
Page renderer
Component decouples backend code
System definition
Implementationnamespaces
Protocols+
Schemas/Types
Webapp development with Clojure + ClojureScript ...
... gives you rapid feedback
… provides a mature full-stack ecosystem
… is demanding to learn, but this will pay-off