Exploring the Clojurescript REPL

TL;DR:

A beginner-level exploration of a ClojureScript REPL session complete with mistakes of the type made by me so that you might avoid these common pitfalls when starting your own ClojureScript adventures.

I love the interactivity of working with code in a Clojure(Script) REPL (REPL = “read-evaluate-print-loop”). Understanding a few basic concepts can help ease the learning curve and give you the tools to bootstrap further exploration. I hope this annotated transcript gives you a headstart in your own ClojureScript REPL explorations!

ClojureScript Quick Start

This session is based on the ClojureScript Quick Start guide which illustrates how to configure a simple ClojureScript project without the need for external tools (like Leiningen). If you’re new to ClojureScript, the ClojureScript Quick Start guide is essential reading and you should read that first or this post won’t make much sense.
Warning! ClojureScript is under heavy development so be aware that if something below doesn’t work it’s probably because you are using an older version of ClojureScript that is missing features available in a newer build. Code in this post is guaranteed to work if you setup your code as described in the ClojureScript Quick Start (which at the time of this article is based on ClojureScript build 3162). I strongly recommend that if you’re new to ClojureScript that you start with this simplified setup and then use build tools like Leiningen or Boot once you understand how namespaces work and you’re comfortable debugging namespace dependency issues.

Adding to the Project

Let’s begin where the ClojureScript Quick Start project left off with a directory named hello-world which contains:

  • An index.html file
  • A repl.clj file
  • A src directory containing a core.cljs file

Here’s what your core.cljs should look like (I’ve added a couple of small things so have something more to work with).

(ns hello-world.core
  (:require [clojure.browser.repl :as repl]))

(defonce conn
  (repl/connect "http://localhost:9000/repl"))

(enable-console-print!)

(println "Hello Cruel World!")          

(defonce init-state {:text "Hello, this is: " :numbers ["one" "two" "four"]})

(defonce app-state (atom init-state))

(defn foo [a b]
  (* a b))

(defn bar [d e]
  (+ d e))

I’ve setup a GitHub repo with the code ready to go (remember to copy the standalone cljs.jar file into the top-level /hello-world/ directory if you clone the repo or nothing will work!).

Starting the ClojureScript Browser REPL

Start a REPL from terminal.app as you did in the Quick Start guide:

=> rlwrap java -cp cljs.jar:src clojure.main REPL.clj
Compiling client js ...
Waiting for browser to connect ...

(in Chrome go to: http://localhost:9000) and then in the REPL you just started you should see:

Watch compilation log available at: out/watch.log
To quit, type: :cljs/quit
If you don’t see the Watch compilation log message right away try refreshing your browser – depending on your configuration it can take a couple of tries to establish a connection.

If you got the ready message, Congrats! You’ve now got a REPL connected to your browser.

Now that we have a basic REPL setup, let’s take a moment to understand how the browser REPL system works:

  1. The java command starts a Java Virtual Machine in terminal.app and loads the ClojureScript jar file (which contains the prebuilt ClojureScript core).
  2. The Clojure main function is invoked and using the information in the repl.clj file it compiles the ClojureScript code including the hello-world/src/core.cljs file into JavaScript and copies it into the out directory.
  3. A basic web server is started on your localhost and waits for connections on port 9000.
  4. The ClojureScript REPL server is started in JVM and waits for a connection from the browser (the REPL client).
  5. When a browser connects to http://localhost:9000 the server delivers the JavaScript files, including:
    • The Google Closure library which is responsible for JavaScript dependency management and optimizing JavaScript compliation. (note that this is “closure” not “clojure”).
    • The compiled ClojureScript core library (originally contained in the cljs.jar).
    • The compiled files for your program.
  6. ClojureScript code typed into the REPL is compiled to JavaScript by the JVM running in the terminal.
  7. The JavaScript code is sent to browser REPL client for execution over port 9000.
  8. The result is sent back to the REPL server in the terminal and displayed.

First Explorations

OK, so now we know the how data flows from the terminal to the browser and back again, let’s figure out how to get around in the REPL.

Having a mental model of your current “location” in the REPL and how to access the vars and functions available is the key to using the REPL effectively. Our first goal then, is to find out which vars are available and how to call them.

When the REPL starts up we’re put into the default REPL namespace which is cljs.user. The first time you fire up the REPL cljs.user is empty but it does have some basic functions defined that have been brought in from the cljs.repl namespace. The first function we’ll use is dir which prints a sorted directory of public vars in a namespace. Let’s try it out:

cljs.user=> (dir cljs.user)
nil

Well, that’s not much help is it? What’s going on here? Like the Clojure function of the same name, dir is showing us the functions that are defined in the namespace cljs.user. Since there are no functions in this namespace we’re not seeing anything displayed in the REPL. Note that dir prints only the functions and vars in the specified namespace and not “all the functions available in all namespaces”. If we define a new var in the cljs.user namespace then we can use dir to see that it’s there:

cljs.user=> (def avariable :foo)
:foo
cljs.user=> (dir cljs.user)
avariable
nil
cljs.user=> avariable
:foo

So far so good. So how do we access code in another namespace like the vars or functions in our hello-world application? To access these functions we first need to require the namespace:

cljs.user=> (require '[hello-world.core :as hello])
nil

…and now we can explore the vars in the loaded namespace hello-world.core

cljs.user=> (dir hello-world.core)
app-state
bar
conn
foo
init-state
nil

Cool! You’ll recognize the functions from the file hello-world/src/hello-world/core.cljs. Next, let’s interact with our application as it is running in the browser:

cljs.user=> app-state
WARNING: Use of undeclared Var cljs.user/app-state at line 1 <cljs REPL>
nil

Bleck… why didn’t that work? The hint is in this part of the error: ...cljs.user/app-state. The call fails because we’re currently in the cljs.user namespace and we’re trying to call a var in the hello-world.core namespace.

Let’s try that again using the fully qualified name:

cljs.user=> (hello-world.core/app-state)
TypeError: hello_world.core.app_state.call is not a function
TypeError: hello_world.core.app_state.call is not a function
... elided ...

Crap. Still not working. What’s wrong? The hint is “…hello_world.core.app_state.call is not a function. This call fails because we’re trying to call the atom app_state as if it were a function. (ClojureScript is a lisp and assumes that the first item inside a set of parens is a function to be evaluated).

To get the contents of a var or atom at the REPL just use the name without parens:

cljs.user=> hello-world.core/app-state
#<Atom: {:text "Hello, this is: ", :numbers ["one" "two" "four"]}>

Yay! Alternatively we can switch to the namespace with in-ns and call the unqualified var name:

cljs.user=> (in-ns hello-world.core)
java.lang.UnsupportedOperationException: nth not supported on this type: Symbol
at clojure.lang.RT.nthFrom(RT.java:857)
at clojure.lang.RT.nth(RT.java:807)
... elided ....
at clojure.main.main(main.java:37)

Arrgh!! Balls. Now what’s happening? Turns out that in-ns (unlike dir) takes a quoted namespace name like so: (notice the quote symbol before hello-world.core)

cljs.user=> (in-ns 'hello-world.core)
nil
hello-world.core=> app-state
#<Atom: {:text "Hello, this is: ", :numbers ["one" "two" "four"]}>

So how do we know if a function takes a quoted symbol or not? I’m not sure… I will pose the question to a more experienced cljs developer and update when I know more.

It’s also useful to mention here that atoms in ClojureScript can be accessed using “@”, which is the way you’d commonly see it in most ClojureScript code[2]:

hello-world.core=> @app-state
{:text "Hello, this is: ", :numbers ["one" "two" "four"]}

Anyway, onwards! Let’s switch back to cljs.user so we have access to the REPL functions for the next step.

hello-world.core=> (in-ns 'cljs.user)

Let’s make a change to our application’s app-state:

cljs.user=>(swap! hello-world.core/app-state assoc :player1 "bob")
{:text "Hello, this is: ", :numbers ["one" "two" "four"], :player1 "bob"}

And if we query app-state we see that it did, indeed, update:

cljs.user=> hello-world.core/app-state
#<Atom: {:text "Hello, this is: ", :numbers ["one" "two" "four"], :player1 "bob"}>

Fun! Now’s a good time to see what’s happening in the browser…

Browser Explorations

In the Chrome tab where your application is running (i.e. the tab that loaded http://localhost:9000), open devtools (menu item: View -> Developer -> Developer Tools) and select the “Console” tab.

At the prompt start typing hello. The console should complete “hello_world” for you indicating that it’s an object in the global JavaScript namespace and which is “known” to Chrome.

(Notice that the original dash in hello-world has been turned into an underscore “_”. This is a feature of the ClojureScript compiler and happens to all names that contain dashes).

The JavaScript object equivalent of our ClojureScript var is: hello_world.core.app_state but instead of a ClojureScript atom it’s a JavaScript object of type “cljs.core.Atom” which we can see if we invoke the object in Dev Tools:

DevTools Console

Exploring ClojureScript Core Namespaces

So we’ve seen how to access your ClojureScript vars from the REPL and where they are and what they look like in the browser. Now let’s explore what other namespaces we have to play with.

While there’s no simple command like Clojure’s all-ns to show all namespaces at the ClojureScript REPL[1], a little digging into the internals of ClojureScript will turn up what we’re looking for. Chrome Devtools is helpful again in this case:

Chrome DevTools

The ClojureScript functions are contained in the cljs object. Start typing ‘cljs’ in the DevTools console. You should see a list of JavaScript objects that are available in the global JavaScript namespace (if you don’t see a popup, try refreshing the browser page).

In addition to the native JavaScript functions associated with the “cljs” object (valueOf etc.) we also find:

  • core
  • repl
  • pprint
  • user

We already know about the cljs.user namespace so let’s explore the cljs.repl namespace from our ClojureScript REPL. Go back to your terminal and type:

cljs.user=> (dir cljs.repl)
apropos
dir
doc
err-out
find-doc
print-doc
pst
source
nil

Interesting. Here we see our old friend dir and other useful functions that are automatically required into the cljs.user namespace when the browser REPL starts up.

doc is essential for learning the ClojureScript core functions:

cljs.user=> (doc reduce)
-------------------------
cljs.core/reduce
([f coll] [f val coll])
f should be a function of 2 arguments. If val is not supplied,
returns the result of applying f to the first 2 items in coll, then
applying f to that result and the 3rd item, etc. If coll contains no
items, f must accept no arguments as well, and reduce returns the
result of calling f with no arguments. If coll has only 1 item, it
is returned and f is not called. If val is supplied, returns the
result of applying f to val and the first item in coll, then
applying f to that result and the 2nd item, etc. If coll contains no
items, returns val and f is not called.
nil

And find-doc is great if you don’t quite know which function you’re looking for.

cljs.user=> (find-doc "reduce")
-------------------------
-kv-reduce
([coll f init])
Reduces an associative collection and returns the result. f should be
a function that takes three arguments.
-------------------------
-reduce
([coll f] [coll f start])
f should be a function of 2 arguments. If start is not supplied,
returns the result of applying f to the first 2 items in coll, then
applying f to that result and the 3rd item, etc.
-------------------------
... and a ton of other stuff (elided)...

So, what’s available in the other clojure namespaces like cljs.core?

cljs.user=> (dir cljs.core)
*
*1
*2
*3
*ClojureScript-version*
*e
*flush-on-newline*
*loaded-libs*
*main-cli-fn*
*print-dup*
*print-fn*
*print-length*
*print-level*
*print-meta*
*print-newline*
*print-readably*
*target*
*unchecked-if*
+
-
->
->>
... elided ...

Whoa billy. That’s a lot of stuff.. you’ve probably figured out already that’s where the bulk of the ClojureScript functions live. Ok, so what happens if you add a new function to hello-world.core and want to make it available in the running browser environment? Let’s try it!

Interactive REPL Development

For me interacting with your running application is what REPL-driven development is all about.

Let’s add a simple function to our hello-world.core namespace by editing the core.cljs file. In your editor add something like the following simple function:

(defn bing [n d]
(/ n d))

Save the file. Because we have the :watch option specified in repl.clj the file should be compiled automatically. Now go back to the REPL to check if it’s in the namespace:

cljs.user=> (dir hello-world.core)
app-state
bar
bing
conn
foo
init-state
nil

Great! now let’s use it:

cljs.user=> (hello-world.core/bing 10 5)
TypeError: Cannot read property 'call' of undefined
TypeError: Cannot read property 'call' of undefined
... elided ...

Bugger.. what happened? If we go back to the browser and inspect the hello_world.core object we see that the bing object isn’t there:

bing before

However, if we refresh the browser and we inspect the var again we see that bing is now available in the hello_world.core object:

bing after

And if we try to call it from the REPL everything works as expected:

cljs.user=> (hello-world.core/bing 10 5)
2

But be aware that if you refresh the page, the browser will re-download your application from scratch and any in-memory vars that you updated from the REPL will be blown-away (not what we want).

Remember when we updated the app-state with a :player1 key? Well, it’s not there anymore:

cljs.user=> hello-world.core/app-state
#<Atom: {:text "Hello, this is: ", :numbers ["one" "two" "four"]}>

Damn. Luckily there’s an easy way to update the application while it’s running in the browser. Just use the :reload option in the require function like so:

cljs.user=> (require '[hello-world.core :as hello] :reload)
nil

Whenever you modify and then save a ClojureScript source file that is being watched (in our case any cljs file in the src directory) you will need to require the namespace again with the :reload keyword to make it available in the execution environment (in our case, the browser). The :reload option appears to be quite smart and maintains the browsers internal state so functions defined before the reload are available after the reload (but I’m not 100% certain about that so don’t quote me!).

That’s It!

I hope you’ve enjoyed this romp through the ClojureScript REPL and it helps you with your own explorations. We’re only just scratching the surface of what’s possible but you now have the tools you need to figure out more advanced interactions. Comments, corrections and suggestions for improvements welcome! Happy trails.

Notes

[1] While ClojureScript does implement a function called all-ns in the cljs.analyzer.api namespace it’s for use by the ClojureScript compiler and not available at the ClojureScript REPL. It’s possible there may be an all-ns available from cljs.repl in the future.
[2] Thanks to Mike Fikes for pointing this out.

Simple Daily Planning Template

TL;DR: Here’s a simple excel template to help you plan your daily routine and (hopefully) increase your productivity.

For the impatient, download the: Daily Planning Template

Daniel Markovitz wrote an interesting article on blogs.HBR.org titled “To-Do Lists Don’t Work”. I agree with Daniel that traditional to-do lists lack “commitment devices” and I’ve definitely felt overwhelmed while staring at a to-do list with 1000+ items. The antidote to this is called “living in your calendar” which means putting everything you need to do in your day onto a calendar format so you can visualize how much time you really have in a given day and to challenge yourself to finish tasks within the time you’ve allotted to them.

The benefit to me is that I feel more comfortable planning my day first, focusing only on the current day’s tasks and then putting myself in “go mode” to just get stuff done. I can fully focus on getting one day’s worth of tasks completed without having to go back to “planning” mode to re-evaluate all the other tasks which are vying for my attention.

The truth is that I ‘m rarely able to fully complete my day as planned (hey, life happens) but I’m WAY more productive when I “live in my calendar” than when I’m ping-ponging between planned and incoming tasks.

Implementation

In the last couple of months I’ve switched from a fairly complicated GTD setup with recurring reminders, synchronized web and iPhone apps, etc, etc. to a simple task outline on Workflowy which I transfer to a daily excel calendar template (attached below). I’m not sure why I didn’t just use my google calendar – there might be a good reason, I just can’t remember it now! The whole setup is much simpler (almost zero overhead to manage) and I’m now more productive (which is the whole bloody point, init!)

Observations

Seeing my todo list as an outline on Workflowy helps me see the forest for the trees and then putting tasks on my calendar helps me be more focused and productive when it’s time to get stuff done. When you’re working off your calendar you’re much more aware of how long tasks are actually taking to get done and although time pressure is typically something that can be a source of stress, setting your own time pressure feels more like a challenge than a burden.

Another interesting finding – the old adage of estimation is very true for me: “When estimating how long something will take to get done – double the estimate and add 50%”. My initial estimate on how long this post would take to write: 30 mins. Time it actually took to write, proofread and publish this article: 1h 27mins (go figure).

Please let me know if it works for you in the comments!

Efficient Text Editing on MacOS

tl;dr Bind Command + “j”, “k”, “l”, and “;” to the cursor movement keys for a more fluid, productive text editing experience on MacOS.

(For the impatient: Jump straight to the implementation)

I recently read a great post by Jamie Buelta titled “Vim speed is not really the point“. In the post, Jamie argues that the benefit for investing the time to install Vim or Emacs keybindings into your muscle memory is not because it makes you a faster coder but because it allows you to focus more of your conscious mind on the logic of programming and less on the administrative thoughts like: “how do I get the cursor to the beginning of that word”. Jamie’s point is that speed is not the goal but rather, it’s the feeling of calm control that is the real reward for all the hard work that you put into learning your code editor.

With that idea in mind I’d like to share with you a rather unusual keyboard binding scheme on MacOS that I find very comfortable and efficient and which helps me to compose text without thinking to much about the mechanics of moving the cursor. This works for all native Mac apps and, with some additional finagling, Emacs too.

The Basics

The basic concept is to bind the cursor movement keys to Command + “j”, “k”, “l” and “;”. This is an idea as old as dirt but I’ve never see anyone implement it MacOS-wide. The obvious benefits of this approach is that it allows you quickly move the cursor while keeping your hands comfortably on the home row in any MacOS app, dialog box, etc.

I’m not sure exactly where the inspiration for this came from but if you’ve ever used vi or WordStar you’ll find this quite familiar. I’ve been using it for many years and I’ve found it works well across many different scenarios whether you’re typing email, blog-posts or coding.

I’ve found that the best configuration for me is to bind “j” to left, “k” to down, “l” to up and “;” to right. Vim users will probably be screaming at the sacrilege but hey, that works best for me (and I’m not a regular vim user so it doesn’t conflict with my muscle memory). If you ARE a regular Vim user then just go ahead and modify the instructions below to your liking, k?

Other Useful Bindings

Moving by word is achieved by pressing Command and Option together with “j” and “;” respectively. I like this because you can very quickly “zero-in” on the character you want to edit by holding or releasing the option key as you get closer to the point you’re seeking towards. It sounds complicated but it ends up being really easy to learn and integrate.

I’ve bound “move to beginning of line” and “move to end of line” to Command + “h” and Command + ‘ (single quote) respectively. It may seem weird to use the single quote character but it feels very natural and I almost never hit the enter key when I’m trying to hit Command + ‘. I should mention here that I chose these keybindings because I felt they were ergonomic and corresponded to the direction of the cursor movement and specifically NOT because the first letter was a mnemonic for the command (YMMV).

Another binding I find useful and use all the time is Command + Option + “k” which is bound to PageDown and Command + Option + “l” which is bound to PageUp. This is especially useful on my MacBook because I always forget where Apple hid the PageUp and PageDown keys (it’s bound by default to Fn + Up Arrow).

Selecting Text

Pressing Shift with any of these combinations allows you to select words. For example, holding Command + Option + Shift and tapping “j” selects by word to the left and Command + Option + Shift + “;” selects by word to the right. “Command + Option + Shift” sounds like a horrendous key combination but it’s actually pretty comfortable if you press the Command key with your left ring finger, Shift with your left pinky and the Option key with your thumb (curled under slightly). Reading the previous sentence aloud still makes it sound pretty horrific but I encourage you to give it a try for a couple of days and then if you still don’t like it THEN you can flame me.

An aspect of this setup that I like is that all modifiers are under your left hand while the movement keys are under your right hand. This avoids the awkward (to me anyway) left-hand or right-hand only keybindings like Command + “a” and Command + “e”.

Details and Implementation

To implement this scheme I use the excellent Keyboard Maestro which at $36.00 US is a steal for all the features it provides. If you are a productivity junkie like me you’ll just love everything that Keyboard Maestro can do for you. You can also the free and open source KeyRemap4MacBook to achieve the same goals but it’s trickier to setup. In this post I’ll show you how to setup this scheme up using Keyboard Maestro.

Firstly, an important element of this setup is to swap the Caps Lock and Command keys. You could achieve the same basic result by leaving the command key in the default location next to the space bar but it would make “move by word” and selecting text a lot more difficult (plus you would loose some geek-cred).

Go to System Preferences -> Keyboard -> Modifier Keys and choose Command next to the Caps Lock drop-down:

MacOS Keyboard Preferences

MacOS Keyboard Preferences

This means that you’ll give up your Caps Lock key but frankly, I’ve never missed it myself (there are ways around this problem but that will be for a future post).

Next, create a group in Keyboard Maestro called “Movement Keys”. This will allow you to easily turn these shortcuts on and off.

In the “Movement Keys” Groups, tap the “new action” button and choose Interface Control -> Type a Keystroke

In the simulate keystroke box tap the right arrow key. You should have the following in Keyboard Maestro:

Keyboard Maestro Editor

Keyboard Maestro Editor

Repeat the above with the following bindings and enjoy the sweet, sweet taste of lightning fast text editing!

Macro Name Hot Key Simulate Keystroke
Move Char Right Command ; Right Arrow
Select Char Right Command Shift ; Shift + Right Arrow
Move Word Right Command Option ; Option + Right Arrow
Select Word Right Command Option Shift ; Option + Shift + Right Arrow
Move Char Left Command j Left Arrow
Select Char Left Command Shift j Shift + Left Arrow
Move Word Left Command Option j Option + Left Arrow
Select Word Left Command Option Shift j Option + Shift + Left Arrow
Move Line Down Command k Down Arrow
Select Line Down Command Shift k Shift + Down Arrow
Move Line Up Command l Up Arrow
Select Line Up Command Shift l Shift + Up Arrow
Beginning of Line Command h Command + Left Arrow
End of Line Command ' Command + Right Arrow
Page Up Command Option l Page Up
Page Down Command Option k Page Down

Files

Here’s a zipped copy of my keyboard movement file for Keyboard Maestro. To install click the Keyboard Maestro icon in the toolbar, choose “Launch Keyboard Maestro Editor”, File -> import macros and select the file.

Caveats

This scheme is really only good for touch typists who want to keep their hands on the home row.

This scheme also overwrites some other common key bindings (e.g. Command + l is “go to location” in Chrome for example). I’ve got around this problem by rebinding those often used to keys off the home row (the u,i,o, and p keys work best in my experience). Since Keyboard Maestro allows you to scope keybindings to each application this ends up working very well and you can reuse the same keys in different apps. Happy editing!

Tip: Check Your Calendar First

Do you ever run into the problem where you sit down at your desk with the goal of getting that important report done only to find that it’s 11am and you haven’t started yet?  Well, here’s a tip for getting off to the right start on your day:

Check your calendar and your todo list before jumping into email.

Pretty simple right? Don’t be fooled – it’s a very powerful technique. Here’s why it works:

Our brains are wired for newness and novelty and so we’re very attracted to the “unread” emails that have appeared in your inbox since the last time you checked it. Once we open the first mail we have unconsciously re-prioritized our day according to the messages, requests and spam that other people have sent us.

By checking your calendar first you remind yourself what hard commitments you have made to yourself and others. Then you check your todo list (you are using a good todo list, right? :-) to remind yourself of your other pending high-priority items. Once you have a clear picture of what your day looks like only then should you check your email for emergency emails.

Now we’re at the brink of a trap that many people fall into (myself included) : If there are no emergency emails then you need to close your email program and get to work on your highest priority item (unless of course if you have a meeting).

It’s a simple idea but surprising difficult to implement. Let me know your thoughts, feedback in the comments.