Calling ClojureScript from JavaScript

Integrating JavaScript and ClojureScript into a single web page is easy, with the right start. JavaScript is the language of the web, for now anyway. However sometimes, you want a more modern, powerful language. Perhaps a language that combines modern functional paradigms with the old school power of Lisp. ClojureScript fits your needs.

ClojureScript is a modern functional Lisp that happens to compile down to optimized JavaScript. The base language is called Clojure. Clojure targets the JVM, .NET, and JavaScript VMs. ClojureScript is the JavaScript variety of Clojure.

ClojureScript leverages the advanced compilation mode of Google’s Closure optimizing compiler—the same one that GWT uses. The JavaScript produced by compiling ClojureScript is much faster than handwritten JavaScript, because Google’s compiler handles all the optimization tricks a single person could never remember to do on the fly.

The first step to using ClojureScript is installing lein. Lein is short for Leiningen. Think of it as make or ant for Clojure. Grab a copy of lein by following the instruction here.

After you’ve got lein up and running, navigate in your terminal/command window to a directory you want a ClojureScript project in. Use the following command to create your project.

lein new mies example

Let’s explain what just happened.

lein is the command for creating and running Clojure projects. new means just that, … Give me a new project. The strange work mies is a ClojureScript project template. Lein takes care of downloading the mies template from the web automagically. And finally, example is the name of your new project.

In theory, we could stop here—mies is a ClojureScript web project template after all—but let’s keep going.

Navigate to, ./example/src/example and you will find the core.cljs file. Usually, Clojure files have the *.clj extension, but this is ClojureScript, so the extension is *.cljs. Change the contents of core.cljs to read as follows.

(ns example.core)

(defn ^:export totallyrandomnumber[]
	;;only returning 42
	(+ 40 2))

All this ClojureScript files does is provide a single function called totallyrandomnumber. Clojure convention is to place dashes between words in function names, but I will ignore convention for this tutorial.

The namespace for our function is example.core. The odd looking command, ^:export, tells Google’s compiler to leave the function’s name available instead of optimizing that too. In some languages this would be the equivalent of making the function public or extern‘ing it.

defn is short for define function. The ;; is Clojure’s comment. The only line of code that does anything is (+ 40 2), which adds 40 + 2 and returns the result.

To compile all this ClojureScript, issue the following command from inside the root of the project. That is the same directory that the src folder sits in. Don’t make the common mistake of entering this command from the same directory that you created the example project in. You have to be in the example folder to successfully build the example project.

lein cljsbuild once

This command creates the all-important minimized JavaScript file from our ClojureScript project. You will find it in the out-adv directory. It is the file called, example.min.js.

Move your optimized *.js file to a directory in your website. Now all you need is an HTML page with some JavaScript to call your ClojureScript function. Copy the following code into a *.html file in the same directory as the example.min.js file.

<html>
  <body>
    <script type="text/javascript" src="example.min.js"></script>
    <script type="text/javascript">
      alert("Randomly answering the question ... "
      	      + example.core.totallyrandomnumber());
    </script>
  </body>
</html>

This web page is about as barebones as a web page can be. The body contains one script tag that imports the minimized JavaScript file we just compiled. The other script tag contains a JavaScript alert() that incorporates a call to our ClojureScript function. Notice that the fully qualified name of the function is used. That means that the namespace is prepended to the function name so the call looks like: example.core.totallyrandomnumber().

One last caution is that you will want to test this on a running web server, and not just from your file system. Sometimes web pages don’t load JavaScript and other files properly when loading directly from a file system instead of grabbing them from a web server.