Skip to content
July 21, 2011 / marrowboy

ClojureScript

On July 20th, at a Clojure Users’ Group meeting in New York, Rich Hickey presented a talk called “I’ll be talking about something new!”. This was a pretty secretive move, and in the end the “something new” was called ClojureScript.

In the past, Clojure had been mainly intended for use on the JVM – ClojureScript has a new target runtime environment: JavaScript. So, simply put, you write Clojure and use the ClojureScript compiler which results in javascript which you can run in your browser, in node.js, or in another JavaScript interpreter.

Get Started

It’s very simple to get started:

$ git clone git://github.com/clojure/clojurescript.git
$ cd clojurescript
$ script/bootstrap
Fetching Clojure...
Fetching Google Closure Library...
Fetching Google Closure Compiler...
Building goog.jar...
Copying closure/compiler/compiler.jar to lib/...

Now you have everything you need. It makes sense to use another directory to work in, so you need to set a couple of environment variables. From the directory you are currently in:

$ export CLOJURESCRIPT_HOME=`pwd`
$ export PATH=$PATH:`pwd`/bin:`pwd`/scripts

Now switch over to a directory of your choice. I’m going to concentrate on getting some ClojureScript to work in the browser, so just following the instructions on the Quick Start page, create file called hello.cljs with contents:

(ns hello)
(defn ^:export greet [n]
  (str "Hello " n))

Then run:

$  cljsc hello.cljs {:optimizations :advanced} > hello.js

This takes 25 seconds, to turn the 56-byte Clojure source into a 29k JavaScript file called hello.js. The JavaScript it creates is heavily optimised, and can be added to an html page like this:

<html>
  <head></head>
  <body>
    <script type="text/javascript" src="hello.js"></script>
    <script>
      alert(hello.greet("ClojureScript"));
    </script>
  </body>
</html>

This loads and as expected we get a popup with “Hello ClojureScript”. Magic.

In Detail

What happened during that 25 seconds is that the JVM started up, loaded Clojure, loaded the ClojureScript compiler (which is written in Clojure), compiled hello.cljs to JavaScript, then called the Google Closure Compiler with advanced-optimisations setting to produce the output JavaScript. So it takes some time. It is quicker to use the REPL but I found that the script in script/repl didn’t work right from other directories – I changed it to this:

#!/bin/sh
rlwrap java -server -Xmx2G -Xms2G -Xmn256m -cp "$CLOJURESCRIPT_HOME/lib/*:$CLOJURESCRIPT_HOME/src/clj:$CLOJURESCRIPT_HOME/src/cljs" clojure.main

(Aside: rlwrap is a program which wraps UNIX readline around the REPL, giving ctrl-r history search, bracket-matching and some amount of tab-completion, use apt-get or whatever to install it (via))

Now I can run the repl script, and build like this:

user=> (require '[cljs.closure :as cljsc])
nil
user=>  (time (cljsc/build "hello.cljs" {:optimizations :advanced :output-to "hello2.js"}) )
"Elapsed time: 19004.057181 msecs"
nil

Takes 19 seconds the first time, but after a few runs through the compile-cycle is about 2.5 seconds. It is slightly quicker to use :simple instead of :advanced, and another advantage is that the JS output is slightly more legible so you stand a better chance debugging it.

So great – so now we’ve got all we need to get using Clojure to build functions which we can call into from JavaScript and use in the browser – this is a big start.

Same same but different

The only difference for certain between JVM-Clojure and ClojureScript is that ClojureScript won’t ever Java interop. But at the moment there are other differences, too. ClojureScript does offer JS-interop, though.

JS interop

For me, ClojureScript is interesting because I can build my server-side app in Clojure using Ring and friends (I like compojure, enlive at the moment), and I can now write my client-side logic in Clojure, too. So what the previous code-sample did was create a function in Clojure that can be called from JavaScript, but what I would like to do is create everything in Clojure. The magic expression is (js* "function") – simply:

(ns hello)
((js* "alert") "HELLO")

Recompile this & reload your index.html – you can see the “HELLO” alertbox straight away, no JavaScript calls required. So this lets us call into jQuery for example. I think that jQuery will end up being wrapped (or replaced) by a ClojureScript library soon enough.

Ajax

For now it will suffice to use jQuery for AJAX calls, for which see my gist. I am looking at the Google Closure libraries as a better alternative.

UPDATE: Yeah, don’t use jQuery. gClosure is much nicer as it’s the closure compiler knows how to deal with it so you can use it like Clojure without having to muck around with object transformation (clj->js). To whit.

Advertisements

5 Comments

Leave a Comment
  1. Anthony / Jul 28 2011 7:09 pm

    Woot? A trivial 3-line function turned into a 25Kb minified JS file???

  2. marrowboy / Jul 28 2011 7:16 pm

    Yep that’s what happened. For comparison, equivalent code becomes about 1.5Kb when compiled for the JVM. This setup is optimized for developers who want to program in Clojure for the web, not for people who want smallest javascript files.

    • Anthony / Jul 28 2011 9:03 pm

      A counter-argument to that is that many people would consider this insane JS file size a show-stopper for anything but toy projects.

      I may want to use Clojure on the web, but I also want the viewers of my webpage to have a good experience, and page load time is part of the UX. That is why we minify/gzip our JS files, to make them smaller and faster to transmit. If ClojureScript is emitting this insane pachyderms then I honestly can’t see its adoption for real web work happening, no matter how cool it is.

      Maybe it is just its early days, and will improve…hopefully.

      • marrowboy / Jul 28 2011 9:19 pm

        GMail uses exactly the same javascript compiler to generate its js. When I load my gmail I get sent over 1Mb of text/javascript. I wouldn’t call GMail a toy project and I think it has a very good UX. The target for ClojureScript is large complex applications which can be hard to develop in JS, and it’s especially sweet for AJAX when the server is also in Clojure.

        So yes, 25k for a three-liner is pretty surprising but there is a Rationale[1] for the approach they’ve taken and I think it’s a compromise which is pretty clearly worth making (sometimes – probably *not* for toy projects, imho).

        [1] https://github.com/clojure/clojurescript/wiki/Google-Closure

  3. Ben / Dec 28 2011 9:00 pm

    Just googled clojurescript and ajax and read this post … and felt the urge to say *thank* *you*. Very informative — and fun! Ben.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: