Rationale for ClojureScript
• JavaScript has reach and is very flexible
• Lisp in C's clothing: closures, functional
constructs
• Not robust or good enough programming in the
large
• Lacks (at least for now) some features like
modules, destructuring
• Has quirks
• Client-service Applications are on the Rise
Slide 3
Slide 3 text
Clojure: Main Language
Features and Philosophy
1. Dynamic development
2. Functional paradigm
3. Lisp
4. Designed to be hosted
Slide 4
Slide 4 text
1. Clojure is Dynamic
• JavaScript has a REPL: in-browser and node
• Clojure has a better one
• Not just something you compile and run, but
something with which you can interact.
• Defining/redefining functions, hot-swapping code
Slide 5
Slide 5 text
2. (Clojure is a Lisp)
• List Processing language
• John McCarthy 1958
• Almost no syntax
• Prefix notation: (operator arg1 arg2)
• (my-function arg1 arg2) = myFunction(arg1, arg2)
• Special forms:
(def x 3)
(defn foo [a b] (+ a b))
(operator arg1 arg2 …)
• Some special forms like def, defn
• No different syntax for control flow
(if condition
(+ 1 2)
(+ 2 3))
(while true
(do it))
Slide 8
Slide 8 text
A modern Lisp
Not that many Parentheses
• Brackets [ ] for vector data and bindings
• '(1 2 3) vs [1 2 3]
• Curly braces {} for maps like JS
• {"name" "John" "surname" "McCarthy"}
• Makes code easier to read compared to other
Lisps
Composite Data Structures
• List '(1 2 3)
• Vector [1 2 3]
• Map {:name "John" :surname "McCarthy"}
• Set #{1 2 3} #{"Apple" "Orange"}
Slide 11
Slide 11 text
Composite Data Structures
• Composable
[{:name "John" :surname "McCarthy"
:hobbies #{"AI" "PL"}}
{:name "Alonso" :surname "Church"
:hobbies #{"PL" "Maths"}]
• Can be used as functions
({:name "John"} :name) —> "John"
Slide 12
Slide 12 text
3. Functional Programming
• Avoid mutable state
• Functions first class
• Immutable data structures
• Recursive iteration instead of explicit loops
• Most parts of most programs should be functional,
and that programs that are more functional are
more robust.
Slide 13
Slide 13 text
Functional Programming
Input Output
f
Object
State
method
Input Output
Slide 14
Slide 14 text
Functional Programming
• Pure functions, more robust code
• Single unit to reason about
• State should be concentrated in a small part of the
application
Slide 15
Slide 15 text
No content
Slide 16
Slide 16 text
State management
• In JS, most data is mutable by default
a = [0, 1, 2]
a.push(3)
a -> [0, 1, 2, 3]
• In Clojure, most data is immutable by default
(def a [0 1 2])
(conj a 3) -> [0 1 2 3]
a -> still [0 1 2]
Slide 17
Slide 17 text
State management with
Reference Types
• Mutable data managed through atoms
(def a (atom [0 1 2])
(swap! a conj 3)
• Roughly equivalent to: (def a (conj a 3))
• a is a reference type: get the real value via @a
• Have to use swap! or reset! to make changes
• Explicit state changes
Note: Vars are mutable to aid development
Slide 18
Slide 18 text
Functional Programming
• Main aim is to process sequence of values
• Transform the whole collection, select a subgroup with
desired properties, or generate a summary of the sequence
(map times-two [0 1 2]
(filter pos? [-1 0 1])
(reduce + [1 2 3])
(reduce * [1 2 3])
(map transform-fn collection)
(filter predicate-fn collection)
(reduce reducer-fn collection)
Slide 19
Slide 19 text
Functional Constructs
• for comprehensions like Python or CoffeeScript
(for [i (range 10)]
(* i i))
• underscore.js provides most of these in JS
• mori.js is even better
Slide 20
Slide 20 text
4. Clojure is Hosted:
Easy JS interop
• #js literal
x = {"foo": "bar"}
(def x #js {:foo "bar"})
• clj->js, js->clj, js-obj functions
• method calls become function calls
myObject.myMethod(arg1, arg2)
(.myMethod myObject arg1 arg2)
Interop with JS
• js/foo to access global foo object
• (.getElementById js/document "a-div")
• document.getElementById("a-div")
• functions in namespaces are accessible in JS using object
access
• Assuming you have myFunction in myLib namespace
• window.onload = myLib.myFunction(arg1, arg2)
Slide 23
Slide 23 text
How ClojureScript works
• Actually a Clojure library that emits JavaScript code
• Reads the code, analyzes (AST), emits JS
• Then uses Google Closure compiler to create final output
• Manage dependencies
• Create optimized and obfuscated code
• Dead code elimination
* from the book "ClojureScript Up and Running" by O'Reilly
Slide 24
Slide 24 text
Rosetta Stone
• http://himera.herokuapp.com/synonym.html
Slide 25
Slide 25 text
Clojure constructs not found
in JavaScript
• protocols: a bit like interfaces in Java
• separate implementation from interface
• same function with different number of arguments
(defn foo
([n] (str "received a single arg" n))
([n m] (str "received two args" n m)))
• destructuring: map multiple variables to multiple values
[name surname] ["John" "Doe"]
Slide 26
Slide 26 text
Namespaces
• Like module pattern via objects in JS
!
!
!
• Google Closure uses this format
• Correspond to matching directory and files
(ns 'foo.bar)
(def x 3)
var foo = foo || {};
foo.bar = foo.bar || {};
foo.bar.x = 3;
Slide 27
Slide 27 text
Essence of Programming
• Generating UI: Views
• Managing State Changes: Store
• Coordinating Processes: Actions
• User action events
• Server calls
• Especially async events
Web
^
Slide 28
Slide 28 text
Managing State Changes
• State should be as concentrated as possible
• Push towards edges
• Do not litter your codebase with state
• Idiom: Use a single atom to hold application state
• Some local state is allowed for temporary things
like hover
Slide 29
Slide 29 text
Om: Library for Building UIs
• Functional UI in a stateful DOM
• Actually a wrapper around Facebook's React
• Most state is stored at the top-level in a single atom
• The UI is built using this single atom
• Each component gets a path to its data Data
locality via cursors (path to specific data)
Slide 30
Slide 30 text
Demo
Slide 31
Slide 31 text
Manage Processes
• Event buses: event oriented programming
• Channels: Communicating Sequential Processes
• Put a value to a channel
• Take a value from a channel
• Sequential Processes
• Process A & Process B
• A & B communicate through a channel
• Rendezvous based unlike event buses
• A waits for B, B waits for A
Slide 32
Slide 32 text
Manage Processes
• Main Problem:
name = raw_input("What is your name")
print "Hello", name
• raw_input blocks
• In JS, we use callbacks, the equivalent would be:
raw_input("What is your name",
function (name) {
console.log("Hello", name); })
• No longer blocking, but we lose the simpler flow
Slide 33
Slide 33 text
Solutions in JS
• Promises sort of fix this:
• raw_input("What is your name")
.done(function (name) {
console.log("hello", name)});
• Becomes harder when multiple processes have to
be managed. ES6 generators (yield, like in Python
a possible solution)
Chan
Process 1 Process 2
puts takes
(go (while true
(
Slide 36
Slide 36 text
Demo
Slide 37
Slide 37 text
How to Get Similar
Functionality in JavaScript
• Code architecture: React + Flux to manage state.
• Explicit and managed state changes
• Immutable data structures: mori.js, immutable.js
• Functional constructs: mori.js, underscore.js
• Namespaces: browserify or webpack
• core.async: ES6 generators, or promises
Slide 38
Slide 38 text
Common Concerns
• How big is the final output?
• Is it fast enough?
• How is the tooling support?
• Debugging
Slide 39
Slide 39 text
Conclusion
• ClojureScript has saner defaults and better
functional programming support
• Knowing ClojureScript makes you a better
developer even if you do not use it for production
• Still in assess phase in Thoughtworks Technology
Radar. (Clojure in Adopt phase)
• Promising, but tooling still weak. IntelliJ Idea
Cursive is getting better.