Tag Archives: Clojure

“Clojure Cookbook” by Luke VanderHart, Ryan Neufeld; O’Reilly Media

Clojure Cookbook

O’Reilly has just published a new book on Clojure, this time from the “cookbook” series. The book includes over 150 practical recipes on doing some common things in Clojure. Each recipe is self-contained and usually very small.

It starts with a detailed walkthrough of primitive and collection manipulations. Then it includes recipes on basic development tasks (REPL, using docs, running programs etc.), I/O, databases (two recipes on SQL, one for each of a handful of NoSQL databases, plus quite a few on Datomic), web applications with Ring, performance optimization, distributed computing (mostly Cascalog, some Storm) and testing.

In my opinion the book is very uneven. It’s very detailed about the primitives and basic collections, but at the same time it doesn’t do justice to state management (atoms, refs, agents) or concurrency. Yet it has two chapters on building a red-black tree. It is very detailed about Datomic, but barely scratches the surface of much more common tools like core.async, core.logic or core.match. It does not include anything about graphics or ClojureScript.

In short, it sometimes pays much attention to some uncommon problems or tools, while giving too little information on more popular pieces. I think the target audience is somewhere around intermediate. I don’t think it’s a good way to get started with the language, but it is a decent, handy survey of some areas of the landscape.

Getting Started with Pedestal on Client Side

I finally got to spend a longer while with Pedestal. It is a pure Clojure web framework, where by pure I mean that you’ll see Clojure on back- as well as front end. For starters I only focused on the front end and that’s what this post is about.

What Is Pedestal?

The documentation is good, but it only explains the fundamental concepts. I think it lacks practical examples and more exhaustive API docs (like inputs and expected outputs of each function, options for each configuration etc.). Or maybe it lacks a tutorial (if I win some time on a lottery, I might write one). There are two good sample applications in their repository: helloworld and chat. Unfortunately, helloworld is very simplistic, and chat is a little bit too complicated for beginners. It does a great job showing off all of the features, but it was a little bit too much for me.

So, after a good while of reading the documentation and reverse engineering the samples, I think I’m finally starting to understand what Pedestal is all about.

On the client side Pedestal is a purely functional, reactive, message-oriented framework. All the state is defined in two pieces: the data model and application model. On the surface each of those models is just a single Clojure map, effectively a tree.

Most of the time you don’t operate on the state directly. You define functions (transforms) that react to messages on specific topics and get current state of data model as argument. They return the new value of the state, and the framework will make it the new data model. Another essential kind of function is emitter: In response to certain messages it emits commands (deltas) to update the application model (like “enable transform”, “disable transform”, “create node”, “set value of node”). Finally, in the application level, you can define functions that change something in the behavior or in DOM in response to those deltas.

Everything goes through this pipeline. If an event happens in GUI, or anywhere in the application, it appends a message to the queue and kicks off all the transforms that bubble up from data model through application model to DOM.

This is a simplistic view that doesn’t do justice to all the features, but I think it’s a good starting point.

Better Sample App for Beginners

During this exploration I wrote another sample application. It’s yet another reincarnation of the TODO app that has a single text entry and a list of everything that has been entered so far. It’s much simpler than the chat demo, and it has plenty of comments explaining what’s going on. This is the kind of application that would help me tremendously during in the learning process, and I hope it saves someone some trouble. You can find the source at Github.

Verdict

My initial verdict of Pedestal? It’s definitely worth a close look! I haven’t built any real apps with it yet, but it looks very promising. It’s a breath of fresh air – I’ve never seen anything similar, especially on the client side with JavaScript. And it feels very appropriate: composed of clean, small, well-defined and isolated pieces with sane flow of information. It appears to lead to much cleaner codebase than JS frameworks like Knockout or Angular with their shared state and dangling functions and callbacks everywhere.

Angular Tutorial Rewritten to ClojureScript

Over the last few months I learned some more ClojureScript and I finally came back to Angular. First I followed their excellent tutorial. Then I decided to rewrite it to plain Clojure and ClojureScript, and it went pretty well.

I made one change on the go – rather than load JSON files directly from disk, it talks to a Ring-provided service.

Raw files are below:

All code is available at GitHub.

It’s almost a one-to-one rewrite from JavaScript. Compared to the original, it is pretty ugly – for two reasons. The first is that I wanted it to work with advanced Closure compiler, so I had to use explicit dependencies. The second is that there is a lot JavaScript interop.

Many of those issues can be mitigated with a glue layer. It is possible to write functions or macros that would automatically generate array syntax for functions with injected dependencies, create functions automatically converting arguments with clj->js, and provide a better replacement for $scope.property = function(...){...}.

I may do that later, but firstly I wanted to have a one-to-one replacement.

ClojureScript Does Not (Always) Need Painkiller

A few weeks ago I shared my confusion about writing object-oriented ClojureScript and a little library called cljs-painkiller. Thanks to the awesome Clojure / ClojureScript community I soon learned much better ways to do it.

Painkiller Example

I complained that I had to write ClojureScript that looks like this:

(defn Bag []
  (this-as this
           (set! (.-store this) (array))
           this))
 
(set! (.. Bag -prototype -add)
      (fn [val]
        (this-as this
                 (.push (.-store this) val))))
 
(set! (.. Bag -prototype -print)
      (fn []
        (this-as this
                 (.log js/console (.-store this)))))
 
(def mybag (Bag.))
(.add mybag 5)
(.add mybag 7)
(.print mybag)

Wrong! Soon after that article appeared on DZone, David Nolen (@swannodette) showed me a few snippets in plain ClojureScript that do the same thing:

(deftype Bag [store]
  Object
  (add [_ x] (.push store x))
  (print [_] (.log js/console store)))

(defn bag [arr] (Bag. arr))
(defn bag [store]
  (reify
    Object
    (add [this x] (.push store x))
    (print [this x] (.log js/console store))))

Much better, isn’t it? And it compiles to fairly idiomatic, interoperable JavaScript, not some higher-level magic.

I am in two minds about the need to expose store like this. One one hand, it makes all the mutable things explicit. On the other, it means you’re exposing much “private” stuff to the consumer, even requiring it from him. To deal with that, you can hide array creation in constructor function:

(defn bag [] (Bag. (array)))
(defn bag []
  (let [store (array)]
    (reify
      Object
      (add [this x] (.push store x))
      (print [this x] (.log js/console store)))))

Backbone Example Revisited

When I was just starting with ClojureScript, I shared an example with Backbone integration. Then I complained it was downright unusable with any less trivial Backbone code.

Here’s what my sample looked like:

(def MyModel
  (.extend Backbone.Model
    (js-obj
      "promptColor"
      (fn []
        (let [ css-color (js/prompt "Please enter a CSS color:")]
          (this-as this
                   (.set this (js-obj "color" css-color))))))))
 
(def my-model (MyModel.))

It turns out it can be rewritten to:

(def MyModel
  (.extend Backbone.Model 
    (reify Object
      (promptColor [this] 
        (let [ css-color (js/prompt "Please enter a CSS color:")]
          (.set this (js-obj "color" css-color)))))))

(def my-model (MyModel.))

Much noise gone. It seems that such reify call is the way to go in this case.

Saved?

I love being proven wrong by the community, and clearly there are better ways to do it than I thought initially. Actually, when I started my adventure with ClojureScript I was quarreling with the compiler – now I finally am beginning to know what I’m doing.

ClojureScript requires some ceremony around object creation, separating behavior from state and its initialization. In some contexts it is too restrictive, in some it’s just fine.

My last example is the Knockout spike where I had JavaScript like this:

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
    this.capitalizeLastName = function() {
        var currentVal = this.lastName();
        this.lastName(currentVal.toUpperCase());
    };
 
}
 
ko.applyBindings(new AppViewModel());

To those unfamiliar with Knockout, firstName etc. are methods. Particularly interesting methods are fullName and capitalizeLastName. Here we have method created by call to ko.computed, wrapping a function that references other methods of this object. Not so bad in an OO language…

… but in ClojureScript apparently the best you can do is what I did back when I was getting started:

(def my-model
  (js-obj
    "firstName" (.observable js/ko "Bert")
    "lastName" (.observable js/ko "Bertington")
    "fullName" (this-as this (.computed js/ko 
                 (fn []  this (.firstName this)), this))))

(.applyBindings js/ko my-model)

I don’t like this at all. This is where I think macros are really necessary. Could be the painkiller, or some special macros just for Knockout integration.

ClojureScript does not always need painkiller, but as your code gets more interesting macroing your way out may be inevitable. I guess you don’t always need to write such OO code, but when you do – be ware.

ClojureScript Painkiller (for OOP)

When I learned and used ClojureScript, I really hated writing code that looks like this:

(defn Bag []
  (this-as this
           (set! (.-store this) (array))
           this))

(set! (.. Bag -prototype -add)
      (fn [val]
        (this-as this
                 (.push (.-store this) val))))

(set! (.. Bag -prototype -print)
      (fn []
        (this-as this
                 (.log js/console (.-store this)))))

(def mybag (Bag.))
(.add mybag 5)
(.add mybag 7)
(.print mybag)

That’s so much ceremony and repeated waste!

I know it’s not how you’re supposed to write ClojureScript, but sometimes you have to (for example when working with OO libraries).

What do you do with such code? Cover it with macros!

So I wrote two little macros that you can just pick up and use right away in your ClojureScript, so that it can look like:

(defn Bag []
  (this-as this
           (set! (.-store this) (array))
           this))

(set-obj-fn Bag.prototype.add [val]
            (.push (.-store this) val))

(set-obj-fn Bag.prototype.print [val]
            (.log js/console (.-store this)))

Or just a this-as shortcut:

(set! (.. Bag -prototype -add)
      (obj-fn [val]
        (.push (.-store this) val)))

Source with complete sample is on github. The library is on Clojars, so to use it all you need is [cljs-painkiller "0.1.0"] in your project.cljs. Enjoy!

Get Started with ClojureScript with Leiningen Templates

When I was about to get started with ClojureScript, I was discouraged by the fact that I apparently had to figure out so much before getting a trivial project up and running.

Eventually I learned, built and showed a minimal application running with just Leiningen and Ring, and a little bit of jQuery in ClojureScript.

Some time later Kyle Cordes showed me cljs-template. It’s a Leiningen template created by Chris Granger, also known as the guy behind Noir and Light Table. That was quite fun. All you need to get a project up and running is:

lein new cljs-template my-project
cd my-project
lein run

That’s it, you’re now running a Noir application with ClojureScript in client (jQuery included). You can start hacking at the CLJS source and see changes in browser immediately.

I soon discovered that it was a few months old, using Clojure 1.3, dated build of ClojureScript and pretty much everything. Eventually (thanks to Kyle and Raynes) I got push access to the project and updated everything, so it should be in even better shape now.

I am not sure where cljs-template is going though, with Noir itself going away. I also found one bit missing: That template is awesome to get up and running and show off a demo, but you would still need to do some manual plumbing to make such a project work for a real application (with leiningen hooks on compilation etc.).

That’s why I created another template: cljs-kickoff. Like my first steps, it’s really minimal: just Ring, lein-cljsbuild and ClojureScript. Fewer files, fewer dependencies, very easy to grasp.

To kick it off, just run:

lein new cljs-kickoff my-project
cd my-project
lein run

It will compile the ClojureScript file included in the project and start Ring server with it.

In another shell, you can run:

lein cljsbuild auto

This will start lein-cljsbuild in the auto-compile mode. Whenever the CLJS source changes, it will be automatically recompiled and the running application will pick it up after reload.

Compared to cljs-template, this template is much smaller and only uses very basic, popular and mature pieces (just Ring and CLJS). It also has all the “real” Leiningen hooks in place: CLJS compilation is included in lein run, lein jar and lein uberjar.

I hope it all makes someone’s life easier by making the first step on CLJS path as easy as possible. Happy hacking!

Using Angular.js with ClojureScript

When I wrote my last post on ClojureScript, I was really hoping someone would jump in and say: “You’re doing it wrong! Here’s how.”

I did get some interesting replies, especially on HackerNews (where that post was briefly on the front page). There really seem to be two camps here: Newbies as confused as I am, and pros who say you just have to invest the time and learn, then you may be able to make good use of some of existing JS frameworks or (better?) roll your own ClojureScript frameworks. They say it’s worth it once your codebase is big enough.

Getting Angular to Work

Anyway, Greg Weber here on my blog noted that you can actually use Angular with Closure – just need to use explicit dependency injection. So far Angular seemed to require the least work with CLJS, so I was happy to give it another shot. I also found this note on minification in Angular docs very helpful.

In the end I’ve successfully rewritten the “todo” sample application. Here’s one way to do it:

(defn add-todo [scope]
  (fn []
    (.push (.-todos scope) (js-obj "text" (.-todoText scope) "done" false))
    (aset scope "todoText" "")))

(defn remaining [scope]
  (fn [] 
    (count (filter #(not (.-done %)) (.-todos scope)))))

(defn archive [scope]
  (fn []
    (let [arr (into-array (filter #(not (.-done %)) (.-todos scope)))]
      (aset scope "todos" arr  ))))

(defn CTodoCtrl [$scope]
  (def $scope.todos (array (js-obj "text" "learn angular" "done" true)))
  
  (def $scope.addTodo (add-todo $scope))

  (def $scope.remaining (remaining $scope))

  (def $scope.archive (archive $scope))) 

(def TodoCtrl
  (array
    "$scope"
    CTodoCtrl))

The last 4 lines are equivalent of using this array syntax in JavaScript:

TodoCtrl = ['$scope', CTodoCtrl];

Another way to do it is setting the $inject property, like this:

(def TodoCtrl CTodoCtrl)
(aset TodoCtrl "$inject" (array "$scope"))

As usually, complete working project can be found at my GitHub repository.

Implementation Details

Function definition

In the above example I’m defining functions on CTodoCtrl by using “factory functions”. I find this slightly more readable, but it also can be done with in-place definitions like this:

(aset $scope "remaining" 
        (fn []
          (count (filter #(not (.-done %)) (.-todos $scope)))))

Unfortunately, I was unable to get it to work with anonymous functions (it compiled to CTodoCtrl.remaining = (function CTodoCtrl.remaining() {...):

(aset $scope "remaining" #(...))

This did not work either (I wish it did!):

(defn $scope.remaining [] (...))

Objects, Arrays

I’m not quite happy with the use of objects here – I would definitely prefer to use Clojure maps like this:

; Instead of:
; (def $scope.todos (array (js-obj "text" "learn angular" "done" true)))
; Do:
(def $scope.todos [{:text "learn angular" :done true}])
; Insetad of:
; (into-array (filter #(not (.-done %)) (.-todos scope)))
; Do:
(filter #(not (:done %)) (:todos scope))

Unfortunately, it seems Angular doesn’t like ClojureScript types and vice versa. Looks like a small, fixable annoyance.

ClojureScript!

It’s still ugly at places and not quite spectacular, but I like using functional programming with ClojureScript instead of JavaScript loops.

I mean replacing this:

var count = 0;
angular.forEach($scope.todos, function(todo) {
  count += todo.done ? 0 : 1;
});
return count;

with:

(count (filter #(not (.-done %)) (.-todos scope)))

And this:

var oldTodos = $scope.todos;
$scope.todos = [];
angular.forEach(oldTodos, function(todo) {
  if (!todo.done) $scope.todos.push(todo);
});

with:

(let [arr (into-array (filter #(not (.-done %)) (.-todos scope)))]
      (aset scope "todos" arr))

Verdict

All in all, I may finally be seeing the light at the end of the tunnel. Integration with Angular looks very promising, after addressing the small interop glitches with type mapping it may be quite expressive and straightforward. I probably will shelve Knockout for now and explore Angular.

Marrying ClojureScript and JS Frameworks – Knockout Edition

A while ago I began to play with ClojureScript and tried to get it to work with popular frameworks. I played with a few of them, most recently with Knockout.js. This post sums up those efforts and my not-so-optimistic view on ClojureScript.

  • I tried “bare” jQuery. It was pretty smooth.
  • I tried Backbone.js. I got it to work on a simple example, though one reader on Twitter rightfully commented that ClojureScript was hideous. Yes, that Backbone example is hideous. Later on I tried to do something less trivial. Eventually I fled in horror, thanks to impedance mismatch between heavily OO Backbone and non-OO ClojureScript sauced with my ignorance in CLJS (and Backbone).
  • I also gave Angular.js a shot. It started really smooth, because Angular proudly states that it doesn’t rely on object-oriented programming so much. It was great. Right to the moment when I started arguing with the compiler renaming my variables, soon followed by discovery that Angular and Closure are no go.

So, the time has come to another experiment – this time Knockout.js. I followed the official tutorial and here is what I eventually came up with.

The Page

The complete page in Hiccup looks like this. Nothing particularly exciting here.

(defn render-body []
  (hp/html5
     [:head]
     [:body
 
      [:p "First name: " [:strong {:data-bind "text: firstName"} "todo"]]
      [:p "Last name: " [:strong {:data-bind "text: lastName"} "todo"]]
      [:p "Full name: " [:strong {:data-bind "text: fullName"} "todo"]]
      
      [:p "First name: " [:input {:data-bind "value: firstName"}]]
      [:p "Last name: " [:input {:data-bind "value: lastName"}]]
      
      [:button {:data-bind "click: capitalizeLastName"} "Go caps"]
   
      (hp/include-js 
        "//ajax.aspnetcdn.com/ajax/knockout/knockout-2.1.0.js"
        "js/cljs.js")
      (hp/include-css "css/todo.css")
      ]))

ClojureScript

The most interesting part is the ClojureScript code. Here’s one way to do it:

(ns hello-clojurescript)

(defn app-view-model []
  (this-as this
           (set! (.-firstName this) (.observable js/ko "Bert"))
           (set! (.-lastName this) (.observable js/ko "Bertington"))
           (set! 
             (.-fullName this)
             (.computed js/ko 
               (fn []
                 (str (.firstName this) " " (.lastName this))) this))
           (set!
             (.-capitalizeLastName this) 
             (fn []
               (.lastName this (-> this .lastName .toUpperCase)))))
  nil
  )

(.applyBindings js/ko (app-view-model.))

Yes, I do need to explicitly return “nil” there. Otherwise it returns this.fullName = ..., and that breaks KO.

It works, but it’s hard to defend it in comparison to the JS equivalent:

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();    
    }, this);
    this.capitalizeLastName = function() {
        var currentVal = this.lastName();     
        this.lastName(currentVal.toUpperCase());
    };
    
}

ko.applyBindings(new AppViewModel());

Complete code can be found at my GitHub repository.

Better Way – Macro

This code can be made a lot better with a custom macro, as the one presented at StackOverflow:

(defvar name_model
    first_name (observable "My")
    last_name (observable "Name")
    name (computed (fn [] (str (. this first_name) " " (. this last_name)))))

(. js/ko (applyBindings name_model));

Now, that would be something!

… except for that defining macros in ClojureScript is harder than in plain Clojure, to the point that I haven’t gotten it to work yet.

Conclusions on ClojureScript

I spent quite a few hours poking at ClojureScript, and I have mixed feelings.

  1. It’s pretty hard to get ClojureScript to work with existing JS frameworks, mostly because using objects in CLJS requires so much ceremony.
  2. Contrary to plain Clojure, “fun” and “productive” aren’t the words that come to mind when I think of my adventures in CLJS. “Frustrating” and “intimidating” are much more appropriate. I’m constantly arguing with the compiler and trying to beat it to do the right thing, not having fun solving problems.
  3. Some stuff can be covered with macros, but all in all it feels very… rigid and constraining. I feel like every once in a while I’m bound to hit another rough corner, spend too much time on it, write another macro, and so on. All that only to bridge the gaps and make ClojureScript look more like… JavaScript. In fact, that feels like writing my own layer of macros to compile JS-like-DSL to ClojureScript.
  4. Perhaps there is a better way and I’m just doing something wrong. Maybe you’re not supposed to use those frameworks at all, but roll your own or use those few written in ClojureScript?
  5. Perhaps all of this makes little sense on such a small scale, and you need something really big to appreciate ClojureScript. You just need to invest many hours in passing the learning curve and macroing your way out. Maybe then it becomes more productive, modular and whatnot. I don’t know, in fact I have too little experience in JavaScript itself to answer such questions. I’m not very optimistic about it, though.

Hello, Backbone and ClojureScript

A few days ago I started learning ClojureScript. I wrote a trivial “hello world” application just to get ClojureScript to compile and execute, and later added some basic jQuery support with jayq.

The time has come to make things a little bit more interesting and add Backbone.js to the mix. I’ve never done ClojureScript or Backbone before, so I’m learning them at the same time with an interesting learning curve.

Anyway, I managed to rewrite the first two examples from Backbone docs to pure CLJS. I made some minor modifications like triggering events on button click and changing main background instead of sidebar.

Here’s my page source (with Hiccup):

(hp/html5 
  [:head]
  [:body
   [:button#clickable-event "Click to trigger an alert from basic Backbone event"]
   [:button#clickable-color "Click to change background color"]
   (hp/include-js 
     "http://code.jquery.com/jquery-1.8.2.min.js"
     "http://underscorejs.org/underscore.js"
     "http://backbonejs.org/backbone.js"
     "js/cljs.js")
   ])

As you can see, it renders a very basic page with two buttons and includes a few JS libraries.

And here’s the CLJS file mixing jQuery and Backbone:

(ns hello-clojurescript
  (:use [jayq.core :only [$]])
  (:require [jayq.core :as jq]))

; ALERT ON CLICK
; Rewrite of http://backbonejs.org/#Events
(def o {})

(.extend js/_ o Backbone.Events)

(.on o "alert" 
  (fn [msg] (js/alert msg)))

(jq/bind ($ "#clickable-event") :click 
      (fn [e] (.trigger o "alert" "Hello Backbone!")))

; MODEL WITH COLOR CHOOSER
; Inspired by http://backbonejs.org/#Model but without sidebar

(def MyModel 
  (.extend Backbone.Model
    (js-obj 
      "promptColor"
      (fn [] 
        (let [ css-color (js/prompt "Please enter a CSS color:")]
          (this-as this
                   (.set this (js-obj "color" css-color))))))))

(def my-model (MyModel.))
 
(.on my-model "change:color"
  (fn [model color]
    (jq/css ($ "body") {:background color})))

(jq/bind ($ "#clickable-color") :click 
         (fn [e] (.promptColor my-model)))

There’s a number of new things (to me) and nonobvious pitfalls. View this side-by-side with Backbone demos, and note:

  • To invoke _.extend(o, Backbone.Events), do (.extend js/_ o Backbone.Events). ClojureScript will correctly transform (.extend js/_ ...) to _.extend(...), and it will copy Backbone.Events as is (no quoting necessary)
  • To distinguish between objects and functions defined elsewhere and in CLJS, always prefix the former with js/name. Works for alert, underscore etc.
  • I had an issue with passing objects (as maps) directly to calls like Backbone.Model.extend(). Tried things like {:promptColor fn} and {"promptColor" fn} to no avail. I finally discovered (js-obj) and it did the trick, but it’s pretty cumbersome. I wonder if there’s a better way.
  • You need some extra work to use this. It has to be bound to a Clojure symbol with this-as macro.
  • On a slightly related note, I really begin to love jayq. In this example I use bare Backbone directly and struggle, and really appreciate jayq bridging the gap to jQuery. I wonder if there is a CLJS wrapper for Backbone.

All in all, it’s an interesting exercise. Just the right learning curve – stimulating, but not discouraging, regularly providing visible feedback.

As usually, complete source is at GitHub. I created a new repository for it, to keep “hello ClojureScript” as small as possible. This new demo probably will grow as I learn more Backbone.

Hello, ClojureScript! (with jQuery)

I decided to give ClojureScript a try. It did not come easy, because I found the official documentation somewhat complicated. I know there is ClojureScript One, but that project also is not as simple as it could be. I don’t want fancy functionality, noir/compojure, enlive/hiccup, and tons of other semi-relevant tools. Bare simplistic HTML and a starting hook for ClojureScript is pretty much all I need for the head start, I can add the rest later.

I was looking for something really minimal, and the first simple example on my Google search was Daniel Harper’s article. I got rid of noir, used up to date versions of libraries, and voila – it’s working!

When I had my first “hello world” alert showing on page load, I decided to make things a little bit more interesting and introduce jQuery. I found jayq from Chris Granger and decided to give it a shot. There’s also a sample app on Chris’ blog that helped me with some issues, namely figuring out how to bind events. It references a few more interesting libs (namely fetch & crate), but I’ve had enough for now. I guess I could spend the whole night chasing such references.

In the end, the interesting pieces of code are below:

project.clj (configured to compile CLJS from src-cljs to resources/public/js/cljs.js):

(defproject hello-clojurescript "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.4.0"]
                 [ring "1.1.6"]
                 [jayq "0.1.0-alpha3"]]
  :plugins [[lein-cljsbuild "0.2.8"]]
  :cljsbuild
  {
   :source-path "src-cljs"
   :compiler
   {
    :output-to "resources/public/js/cljs.js"
    :optimizations :simple
    :pretty-print true
    }
   }
  :main hello-clojurescript.core
  )

core.clj (trivial app, with Ring wrapper configured to serve JS resources):

(ns hello-clojurescript.core
  (:require [ring.adapter.jetty :as jetty]
            [ring.middleware.resource :as resources]))


(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body 
   (str "<!DOCTYPE html>"
        "<html>"
        "<head>"
        "</head>"
        "<body>"
        "<p id=\"clickable\">Click me!</p>"
        "<p id=\"toggle\">Toggle Visible</p>"
        "<script src=\"http://code.jquery.com/jquery-1.8.2.min.js\"></script>"
        "<script src=\"js/cljs.js\"></script>"
        "</body>"
        "</html>")})

(def app 
  (-> handler
    (resources/wrap-resource "public")))

(defn -main [& args]
  (jetty/run-jetty app {:port 3000}))

hello-clojurescript.cljs (this one gets compiled to JavaScript):

(ns hello-clojurescript
  (:use [jayq.core :only [$ delegate toggle]]))

(def $body ($ :body))

(delegate $body :#clickable :click
          (fn [e]
            (toggle ($ :#toggle))))

Complete source code with instructions can be found at my GitHub repository.

At the moment I see the following issues:

  • I’m really green at ClojureScript. Tons to learn here!
  • The JavaScript file compiled from this trivial example is 13k lines long and weighs about 500 kb. Doh! Fine for local development on desktop, not that good for targetting mobile.
  • The official docs for ClojureScript are really… discouraging. Just like core Clojure documentation, they are pretty academic and obscure.
  • Docs for jayq are… Wait a minute, nonexistent? At least it’s a fairly thin adapter with small, comprehensible codebase.