Slide 1

Slide 1 text

Üstün Özgür @ustunozgur JsIst 2014 ClojureScript

Slide 2

Slide 2 text

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))

Slide 6

Slide 6 text

(operator arg1 arg2 …) (+ 1 2) => 3 (+ 1 2 3) => 6 (* (+ 2 3) 4) => 20 No precedence rules. Read inside out

Slide 7

Slide 7 text

(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

Slide 9

Slide 9 text

Primitive Data Structures • Number: 1, 2e3 • String: "JsIst 2014" • Characters: \A, \b • Regex: #"\d{3}" • Symbol: 'foo, 'bar • Keywords: :foo, :bar

Slide 10

Slide 10 text

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)

Slide 21

Slide 21 text

4. Clojure is Hosted: 
 Easy JS interop • anObject.aProperty
 (.-aProperty anObject) • myobject.method1(arg1).method2(arg2) 
 
 (.. myobject 
 (method1 arg1)
 (method2 arg2))


Slide 22

Slide 22 text

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)

Slide 34

Slide 34 text

Clojure's approach: core.async • (def my-channel (chan)) • (defn event-handler []
 (put! my-channel 1)) • (go (while true
 (

Slide 35

Slide 35 text

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.