Diving into clojurescript

What is it

Hosted language

A language that targets different platforms

Sits and integrates on a host platform

Maintains access to host and its ecosystem

Hosted language

Clojure   ☛   JVM

ClojureScript   ☛   JavaScript

JavaScript Runtimes:




About the Language

Lisp family


Functional programming language

  • Immutability by default
  • First class functions
  • Programming with values
  • Declarative-ish (map, filter, etc)

A practical language

  • Not pure fp
  • Really easy to interop
  • You can step out of the defaults
    when necessary

Differences from others

How is it different from coffeescript, typescript, ...?

Changes some JavaScript semantics (to be saner)

  • Equality (values)
  • Falsy/Truthy
  • Sane scoping (-hoisting)

Provides a consistent full language and ecosystem

  • Modules
  • Package management
  • Great standard lib
  • Good practices and philosophy

Cool stuff in clojurescript

Values FTW

Immutable by default

Cool stuff in clojurescript

Concise and expressive

Cool stuff in clojurescript

We will see more through the workshop!

To the code!

Super basics


  • Lighttable
  • Git
  • Leiningen

Small intro to Lighttable

Pmeta + Space
Tabs and Tabsets
Evaling stuff

Code Samples


git clone git@github.com:joakin/diving-into-clojurescript-exercises.git

Connect to Lighttable UI

Code samples are in basic/

Prerequisites 01-pre.cljs

Exercise 01.cljs

Solutions are in 01-sol.cljs


Basic syntax






Interactive TUTORIAL


git clone git@github.com:swannodette/lt-cljs-tutorial.git

Add lt-cljs-tutorial to workspace

Open lt-cljs-tutorial.cljs

Add Connection: Lighttable UI

Start evaling!

Getting the hang


Do it yourself

Check the docs

Look at the community results (Follow top members)

Lets make some apps

The artsy wall

We are going to walk through the creation of a canvas fullscreen app

A wall of colorful squares that vibrate


Steps are stored in src-steps (see README)

Interesting things to learn

  • Live coding
  • Namespaces
  • Including external libraries
  • Source maps
  • JS interop

LT plugins web app

We are going to make a web app that will consume a service

via ajax and will render the contents.


Steps are in the README

Project management


  • Create new projects (templates)
  • Fetch dependencies for your project
  • Run tests
  • Run a fully-configured REPL
  • Compile sources
  • Run the project
  • Compile and package projects for deployment
  • Publish libraries to repositories such as Clojars
  • Automation tasks (leiningen plug-ins)

lein help tutorial | less

Creating New projects

lein help new

Clojurescript templates

lein new mies awebsite

How do I compile ClojureScript?


Leiningen plugin for compiling ClojureScript

In project.clj 

  :plugins [[lein-cljsbuild "1.0.2"]] 

Sample conf:

  :cljsbuild {
:builds [{:id "awebsite"
:source-paths ["src"]
:compiler {
:output-to "awebsite.js"
:output-dir "out"
:optimizations :none
:source-map true}}]})

lein cljsbuild once awebsite # just build once

lein cljsbuild auto awebsite # watches changes and recompiles incrementally

Development workflow

  1. Launch compiler watch
  2. Open project in LightTable
  3. Open browser tab with index.html
  4. Live eval!
  5. Docs
  6. Autocomplete
  7. Watches

Compilation modes

Clojurescript compiler features several compilation modes

project.clj with all the options commented

Each mode has different tradeoffs:

  • Development speed
  • Multiple files vs 1 file
  • Code minification
  • Code optimizations

 Clojurescript compiler    cljs standard library & js

Google closure compiler  merging files, minification, optimizations

Optimizations: none

  • No optimizations
  • Lots of files
  • Fastest compilation (& incremental)
  • Dev oriented
  • Specific imports in html

:cljsbuild {
:builds [{:id "awebsite"
:source-paths ["src"]
:compiler {
:output-to "awebsite.js"
:output-dir "out"
:optimizations :none
:pretty-print true
:source-map true}}]}

<script src="out/goog/base.js" type="text/javascript"></script>
<script src="awebsite.js" type="text/javascript"></script>
<script type="text/javascript">goog.require("awebsite.core");</script>

Optimizations: Whitespace

  • Cleans whitespace and comments
  • One file
  • "Fast" compilation (less than none)
  • Readable JS

:cljsbuild {
:builds [{:id "awebsite"
:source-paths ["src"]
:compiler {
:output-to "awebsite.js"
:output-dir "out"
:optimizations :whitespace
:pretty-print true
:source-map true}}]}

<script src="awebsite.js" type="text/javascript"></script>

Optimizations: SIMPLE

  • One file with simple optimizations
  • Slower compilation
  • One import in the html

:cljsbuild {
:builds [{:id "awebsite"
:source-paths ["src"]
:compiler {
:output-to "awebsite.js" ; No output-dir (only the file)
:optimizations :simple
:pretty-print true
:source-map "awebsite.js.map"}}]} ; Sourcemaps are a file now, not true

<script src="awebsite.js" type="text/javascript"></script>

Optimizations: ADVANCED

  • One file (smallest size)
  • Slowest compilation
  • One import in the html
  • Agressive optimizations, minification and code rewrites
  • Performance  and size gains

:cljsbuild {
:builds [{:id "awebsite"
:source-paths ["src"]
:compiler {
:output-to "awebsite.js"
:optimizations :advanced}}]}

<script src="awebsite.js" type="text/javascript"></script>


Options pretty-print and source-maps are optional.

They increase compilation time.

(Incrementally not so much)


Use :optimizations :none with :pretty-print true and :source-maps true

for development workflows (using lein cljsbuild auto (pure delight))

Use :optimizations :advanced for staging and production.

(Staging with :source-maps and :pretty-print, production without).

Some informal benchmarks

lein cljsbuild once

Successfully compiled "awebsite.js" in 9.214 seconds. Successfully compiled "awebsite-w.js" in 14.045 seconds. Successfully compiled "awebsite-s.js" in 19.269 seconds. Successfully compiled "awebsite-p.js" in 18.701 seconds.

lein cljsbuild auto

Successfully compiled "awebsite.js" in 0.05 seconds. Successfully compiled "awebsite-w.js" in 4.126 seconds. Successfully compiled "awebsite-s.js" in 5.918 seconds. Successfully compiled "awebsite-p.js" in 4.188 seconds.

Some informal sizes

To be fair, in out  there are also cljs and sourcemap files, so size is smaller
(about 900Kb)

Note that with advanced, we got a 10x reduction on size.
(And it's probably faster)


We can distinguish 3 kinds of libraries that we can use

(and require different treatment)

  1. ClojureScript libraries
  2. Google Closure compatible libraries
  3. Other libraries from the JS ecosystem

Clojurescript libraries

Hosted in lein compatible repos (clojars)

How to find them:

Github search


Google groups

Or Google

Just include them in your project.clj and go:

:dependencies [[org.clojure/clojure "1.5.1"] [org.clojure/clojurescript "0.0-2173"] [rm-hull/monet "0.1.11"]]

Restart the compiler so that it downloads it

Google Closure

Big set of cross browser libraries written by Google



API, importing & real_world_usage

Lots of interesting stuff: Format, Color, Events, Dom, Style, ...

Takes advantage of Advanced compilation

(deletes code you don't use and inlines code where it can)

Google Closure

The compiler has and includes as necessary a version of the closure libs

You can specify a specific version of the google closure libraries:

:dependencies [[org.clojure/clojure "1.5.1"] [com.google.javascript/closure-compiler "v20131014"] [org.clojure/clojurescript "0.0-2173" :exclusions [com.google.javascript/closure-compiler]]

Google closure compatible libs

Libraries written with the closure compiler optimizations in mind.

Not a whole lot of them.

They take advantage of code optimizations and compiler errors (docs)

Example (Download react to your project):

:compiler { ; ... rest of arguments :foreign-libs [{:file "reactjs/react.js" :provides ["React"]}] :externs ["reactjs/externs/react.js"]}

Other libraries

Almost all of the JS libs.

Include the code in your project,

If it has externs, you include them:

          :preamble ["react/react_with_addons.min.js"
                     "gifjs/dist/gif.js"] ; or link them in the html
          :externs ["react/react_with_addons.js"

Most of them don't so, options:

  1. Include the library as its own externs
  2. Try to autogenerate them with lein-externs
  3. Write a dummy externs-whatever.js 

    Other libraries


    HUGE ecosystem

    Lots of good libraries

    (moment.js, react.js, hammer.js, bluebird, async, d3.js, bacon.js, ...)


    No optimizations or unused code removal

    Bigger size of bundle because of libraries

    We have to take care of externs with advanced


    If there is a good cljs lib, use that. Otherwise, go wild.

    Some Cool cljs libraries

    Secretary Client side router
    Processing.cljs Wrapper over processing.js
    Dommy Enfocus Domina Dom manipulation and templating library
    Om Reagent Interface to React.js (web apps)
    Javelin Spreadsheet-like dataflow programming
    Monet Easy and performant canvas and visuals
    Jayq Idiomatic cljs - jQuery wrapper
    cljs-ajax cljs-http HTTP and AJAX library
    Lucuma Web components
    Servant Web workers
    cljs-time Date and time library
    Inkspot Colors and swatches



    Live development is no substitute for tests

    Several options:



    Full complete test library (port of the clojure version)

    Well mantained and documented

    To use it just add it to your plugins in project.clj

        :plugins [[com.cemerick/clojurescript.test "0.3.0"]]

    • Run tests from the repl
    • Run tests each time cljsbuild compiles
    :cljsbuild {:builds [ ... ]
                :test-commands {"unit-tests" ["phantomjs" :runner
    :test-commands {"unit-tests" ["node" :node-runner
                                  ; extra code/files here...


    Simple and easy to understand

    (deftest somewhat-less-wat (is (= true (some-function "whatever"))))

    Both sync and async support

    (deftest ^:async timeout
      (let [now #(.getTime (js/Date.))
            t (now)]
          (fn []
            (is (>= (now) (+ t 2000)))


    BDD style testing (specs)

      :dependencies [[org.clojure/clojure "1.5.1"]]
      :profiles {:dev {:dependencies [[speclj "3.0.0"]]}}
      :plugins [[speclj "3.0.0"]]
      :test-paths ["spec"]
    :cljsbuild {:builds        {:dev  {:source-paths ["src/cljs" "spec/cljs"]
                                       :compiler     {:output-to "path/to/compiled.js"}
                                       :notify-command ["bin/speclj" "path/to/compiled.js"]}
                :test-commands {"test" ["bin/speclj" "path/to/compiled.js"]}}

    (ns sample.core-spec
      (:require-macros [speclj.core :refer [describe it should should-not run-specs])
      (:require [speclj.core]
                [sample.core :as my-core]))
    (describe "Truth"
      (it "is true"
        (should true))
      (it "is not false"
        (should-not false)))


    Jasmine based testing (used with Karma)

      :dependencies [[im.chit/purnam "0.4.3"]]

    (describe "Addition"
        (it "should add things"
          (is (+ 1 1) 2)))

    Example config and video for running with karma

    Purnam also contains a bunch of macros for making
    js interop more similar to JS than to ClojureScript.


    There are more, and also wrappers for JS libraries.

    You could ignore all this and just use a JS library for testing (interop)


    Property-based testing

    Instead of enumerating expected input and output for unit tests,
    you write properties about your function that should hold true for all inputs.


    (def sort-idempotent-prop
      (prop/for-all [v (gen/vector gen/int)]
        (= (sort v) (sort (sort v)))))
    (tc/quick-check 100 sort-idempotent-prop)

    You can usit standalone or integrated in your clojurescript.test suite
    (defspec first-element-is-min-after-sorting ;; the name of the test
             100 ;; the number of iterations for test.check to test
             (prop/for-all [v (such-that not-empty (gen/vector gen/int))]
               (= (apply min v)
                  (first (sorted v)))))


    Code generating/rewritting code that gets run at compile time.

    (Code is data, as you have seen)

    ClojureScript macros are written in clojure (.clj files)

    Reading, evaluation and macros

    Writing macros

    Super powerful, useful, language is infinitely extensible by users

    Complicated to debug, best avoided unless necessary (maybe)


    (defmacro when "Evaluates test. If logical true, evaluates body in an implicit do." {:added "1.0"} [test & body] (list 'if test (cons 'do body)))
    (macroexpand '(when (the-cows-come :home) (call me :pappy) (slap me :silly))) ; => (if (the-cows-come :home) (do (call me :pappy) (slap me :silly)))

    (defmacro unless "Inverted 'if'" [test & branches] (conj (reverse branches) test 'if)) (macroexpand '(unless (done-been slapped? me) (slap me :silly) (say "I reckon that'll learn me"))) ; => (if (done-been slapped? me) (say "I reckon that'll learn me") (slap me :silly))


    They are a tough topic, and great books and articles are available.

    Look for Clojure macros, not ClojureScript specifically

    Super powerful, enable users to extend the language via libraries

    in ways inconceivable in other languages (JS? Damn ECMA)

    We will see the power in the next section.

    Some uses:

    Rewrite code (unless, core.async)

    New syntax constructs

    Optimize code (compile time) (dommy)

    Sweet JS

    Mozilla leaded effort to have macros in JavaScript

    Opt-in macros

    More verbose because syntax (code is not data),

    but brings the power and responsibility to JS

    Example: ES6 syntax, Ki (lisp+mori)


    Great philosophy, vision, community and people

    with a great language produce awesome powerful things


    Go style concurrency (CSP) implemented as a library!

    Turns syncronous looking code into CPS (callbacks)

    Concurrent code in single threaded JS!

    (defn init []
      (let [clicks (listen (dom/getElement "search") "click")
            results-view (dom/getElement "results")]
        (go (while true
              (<! clicks)
              (let [[_ results] (<! (jsonp (query-url (user-query))))]
                (set! (.-innerHTML results-view) (render-query results)))))))
      (defn get-user [id]
    (let [out (chan)]
    (db-query-user {:id id} (fn [user] (put! out user)))))

    (defn update-user [user]
    (db-update-user user (fn [err] (put! out err))))

    (def handler [req res]
    (let [user (<! get-user (.id req))
    result (<! update-user user)]

    (.send res (if (nil? result) "OK" "BROKE"))))


    (let [c1 (chan)
          c2 (chan)]
      (go (while true
            (let [[v ch] (alts! [c1 c2])]
              (println "Read" v "from" ch))))
      (go (>! c1 "hi"))
      (go (>! c2 "there")))


    (go (try
          (let [tweets    (<? (get-tweets-for "swannodette"))
                first-url (<? (expand-url (first (parse-urls tweets))))
                response  (<? (http-get first-url))]
            (. js/console (log "Most recent link text:" response)))
          (catch js/Error e
            (. js/console (error "Error with the twitterverse:" e)))))

    10.000 concurrent processes
    100.000 DOM updates
    Local event loops


    An optimized pattern match and predicate dispatch library for Clojure.

    (doseq [n (range 1 101)]
        (match [(mod n 3) (mod n 5)]
          [0 0] "FizzBuzz"
          [0 _] "Fizz"
          [_ 0] "Buzz"
          :else n)))

    (let [x 1 y 2]
      (match [x y]
        [1 b] b
        [a 2] a
       :else nil))

    (let [x {:a 1 :b 1}]
      (match [x]
        [{:a _ :b 2}] :a0
        [{:a 1 :b 1}] :a1
        [{:c 3 :d _ :e 4}] :a2
        :else nil))
    (let [x [1 2 3]]
      (match [x]
        [[_ _ 2]] :a0
        [[1 1 3]] :a1
        [[1 2 3]] :a2
        :else :a3))


    Prolog-like relational programming, constraint logic programming,

    and nominal logic programming for Clojure

    (run* [q]
      (== q true))
    ;;=> (true)

    (run* [q] (membero q [1 2 3]) (membero q [2 3 4]))
    ;;=> (2 3)

    (run* [q] (== {:a q :b 2} {:a 1 :b 2}))
    ;;=> (1)

    (run* [q] (fresh [a] (membero q [1 2 3]) (membero a [3 4 5]) (== q a)))
    ;;=> (3)


    Gradual typing in Clojure, as a library.

    (ann ^:no-check foo (Fn [Number -> Number])) (defn foo [a] 'a) (ann bar [Number -> Number]) (defn bar [b] (+ 2 (foo b)))


    Learn new things that suppose significant brain effort

    Bring what you learned to your daily work (at least the concepts)

    Embrace immutability (eases reasoning about code)

    Play and have fun

    Where to get help


    Google Groups

    irc #clojurescript on freenode.net






    Diving into ClojureScript

    By Joaquin Oltra