4 Bootstrapped ClojureScript REPLs

ClojureScript is a compiler (or transpiler, if you will), that turns ClojureScript code into JavaScript. This ClojureScript compiler is written in Clojure, meaning you still need a Java environment to run it. Only after the compilation is done can you forget about Java and just run the target JavaScript code on your favorite JavaScript environment.

Clojure and Java have provided a solid foundation for developing ClojureScript, much of the Clojure infrastructure could be reused, and the Google Closure Compiler, a Java project, has been indispensable for providing optimized output.

Still the dependency on a Java environment has some downsides. The startup time of the JVM is notorious, and while it's possible to run compiled ClojureScript code without a JVM, it's not possible in that case to compile new code on the fly. For a long time this prohibited building pure-ClojureScript REPLs.

To address these issues, "bootstrapped" ClojureScript was introduced. In the context of compilers "being bootstrapped" means that a compiler is able to compile its own source. This is also called "self-hosting". If ClojureScript compiler can compile itself, than the result is a ClojureScript compiler that can run on JavaScript, instead of Java. (remember that Java relates to JavaScript like carpet relates to car, we're talking about two very different animals here.)

Some key parts of the infrastructure had to be ported to CLJS (or CLJC), but now that bootstrapped ClojureScript is a fact this opens up some exciting new possibilities. Note that for typical production app, the Java-based ClojureScript compiler is still, and probably always will be, the way to go. For building ClojureScript REPLs in JavaScript environments however it's a perfect choice.

Planck

Planck is a ClojureScript REPL that runs in your terminal and is based on JavaScriptCore, the JS engine that ships with WebKit. It is available for Mac and Linux.

Planck's developer, Mike Fikes, has gone through great lengths to build a polished, user-friendly product. This is one of the most "modern" Clojure* REPLs, featuring colorized output, pretty printing of results, and readline-like line editing and history search based on linenoise. Planck also makes the cljs.repl helper functions like doc and find-doc available, which isn't a given in all ClojureScript REPLs.

If you ever wanted to use Clojure to write scripts, but were frustrated by how slow it boots up, then Planck is for you. You can even add a "shebang" line to make scripts self-contained, and Planck provides a handful of namespaces that expose JavaScriptCore APIs to interact with the outside world.

To get started follow the install instructions, then simply run planck and try it out!

Planck comes with comprehensive built-in documentation of all supported command line flags. For more in-depth info check out the Planck User Guide.

$ planck -h

Here's an example of a Planck script that uses the Github API to show the list of repositories for a given user.

#!/usr/bin/env planck
(ns stargazers.main
  (:require [planck.http :as h]))

(defn github-get [path]
  (h/get (str "https://api.github.com" path)
         {:headers {"User-Agent" "Plank 2.0"
                    "Accept" "application/vnd.github.v3+json"}}))

(defn get-repos [username]
  (-> (str "/users/" username "/repos")
      github-get
      :body
      js/JSON.parse
      js->clj))

(defn -main [& args]
  (let [username (first args)]
    (if username
      (doseq [repo (get-repos username)]
        (let [{:strs [name stargazers_count watchers language description]} repo]
          (println (str name " (" language ")\t🟆 : " stargazers_count "\t👓 : " watchers))
          (when description
            (println description))
          (println)))
      (println "Usage:  stargazers <github username>"))))

(set! *main-cli-fn* -main)

Lumo

Lumo has many similarities with Planck. It is a standalone ClojureScript REPL suitable for scripting. It is available on Mac, Linux and Windows, so it does have a leg up on Planck when it comes to platform support.

Where Planck is based on JavaScriptCore, Lumo is based on Node.js, thus holding the promise of integrating and bridging the gap with the NPM ecosystem.

It is still early days for Lumo, it lacks the documentation that Planck has, and also doesn't yet have any of the "ergonomic" features. Nevertheless it's a project to watch.

The easiest way to install Lumo is through npm:

$ npm install -g lumo-cljs

You can have a look at its options with

$ lumo -h

The only other source of information so far is a scant README in the Lumo repository, and the Announcement Blog Post.

Calvin

Calvin is not a REPL itself, but an invaluable tool when working with Planck or Lumo. Both REPLs are able to load ClojureScript namespaces from JARs, but you need to manually manage the classpath.

Calvin makes your life easier by parsing the project.clj file, and figuring out the right classpath for the current project, so all the libraries that it depends on are available from a ClojureScript REPL.

Calvin is still alpha level software.

Replumb

Not a full featured REPL in itself, but still worthy of a mention. Building on top of bootstrapped ClojureScript isn't for the faint of heart. There's still a lot of infrastructure you need to provide depending on the environment you're targeting, and your specific use case. Replumb tries to get most of that boilerplate out of the way so you can focus on building cool stuff.

KLIPSE

Klipse is a "fiddle" style web-based playground for ClojureScript. Enter some ClojureScript, and it will show you the compiled JavaScript, as well as the output from running your code.

Klipse is built on Replumb. With the Klipse plug-in you can add make code snippets interactive, for example in library documentation or in a blog post.

Node.js bootstrapped REPL

We already talked about the Node.js REPL that comes with ClojureScript. That one still requires Clojure though, just like the other built-in REPLs.

It's also possible to build a Node.js based REPL with bootstrapped ClojureScript, which is what the author of the cljs-repl NPM package did.

The package hasn't been updated since it's first release, and the version of ClojureScript it's based on is getting out of date. For most purposes if you're on a supported platform you're better of going with Planck. cljs-repl is still a fun package to play around with though, since it allows you to use Node.js' API's from ClojureScript scripts.