Clojure is a dynamic, functional programming language that is a joy to write. I’ve been writing it professionally for the last six months and wanted to share something I wish existed when I first got started.
This guide, therefore, is primarily aimed at:
- Programmers coming from a different language who have decided to try Clojure;
- Programmers that are writing Clojure for the first time professionally who primarily want a quick way to get a reliable environment up and running, freeing up more time to focus on learning the language itself.
Hopefully after reading this post, you can quickly start to form a workflow for tinkering away at Clojure code in very little time.
I will assume that you are using a relatively up to date version of macOS and understand how to use Homebrew to keep the scope of this guide relatively focused.
While Homebrew also works on Linux, I’ve not personally used it, so cannot vouch if the commands have parity.
Here are some commands to run for Homebrew:
brew install adoptopenjdk clojure leiningen brew cask install visual-studio-code
The only Visual Studio Code extension you will need to be productive with Clojure applications is Calva so make sure to have it installed.
Visual Studio Code’s User Interface
I will be using some terminology that is specific to Visual Studio Code and its UI elements.
To reduce confusion, please make sure to read this document to familiarise yourself with elements of the User Interface.
In this next part, we’re going to:
- Create a new Clojure project using Leiningen.
- Connect to the REPL using Visual Studio Code and Calva.
- Evaluate Clojure expressions directly in your editor.
- Evaluate and run tests directly in your editor.
Create a new Clojure project
Inside the directory you want to create your Clojure project, run
lein new clojure-sandbox
Open the newly created
clojure-sandbox directory inside Visual Studio Code.
A large part of building software with Clojure is the REPL. Most programmers are probably familiar with the concept of a REPL from other programming languages (
irb for Ruby,
python3 for Python, etc.).
In Clojure things are taken one step further. A REPL instance created with Leiningen has a network port that allows incoming connections.
Since this port is opened over a socket, anything with access to that port can connect to it.
The simplest way to open up a REPL instance is to run the command
lein run in the
We can take things a step further, however, by opening up and connecting to a REPL instance from Visual Studio Code using Calva.
Calva takes care of all of this for us by providing a command called
In Visual Studio Code
- Bring up Visual Studio Code’s command palette.
- Type in
Jack-Inand select the option
Calva: Start a Project REPL and Connect (aka Jack-In)
- Select the
You should be connected to a REPL instance and ready to evaluate some code.
Evaluating Clojure Forms
By default, Calva opens a REPL window on the right hand side after Jack-In which I will refer to as the Calva REPL going forward.
You can start to evaluate Clojure forms in the Calva REPL just like any other REPL. Type in an expression, press the return key and observe the feedback – e.g. typing
(+ 2 2) followed by the return key will return
Since you have jacked into a REPL connection, you can tinker around with Clojure code in your editor and evaluate the code you write. This workflow is known in the Clojure community as REPL driven development and is a powerful paradigm.
(+ 2 2) anywhere in
core.clj and then, with your cursor anywhere on that line, you can evaluate the result of this form by pressing
Ctrl + Command + C and
E or selecting
Calva: Evaluate Current Form in Visual Studio Code’s command palette. This will output
4 to the output window.
Calva: Evaluate Current Form in REPL Window in Visual Studio Code’s command palette will evaluate output the evaluation to the REPL window instead of the output window.
I prefer using the output window, especially on my laptop as I can close the REPL window and just use the output window for my feedback loop, saving me precious screen real-estate.
The choice of outputting to the output window or REPL is a standard evaluation pattern in Calva. There are other options to output which you should play around with.
Going forward I will focus on outputting the result to the output window, as that is my personal preference (but feel free to use the output type you prefer).
Once you start to write slightly more complex Clojure, then evaluating the result of a form might not do what you expect (e.g.)
(let [name "Muyiwa"] (str "Hello " name))
If your cursor is on
"Hello " and try to evaluate, you will get a syntax error because we are trying to evaluate and incomplete form. If your cursor is on
name then it will evaluate to a
Essentially, for use-cases like this, you want Calva to evaluate the top-level form. If you start typing
Top Level in the Visual Studio Code command palette, you can see your options. The shortcut to evaluate the top level form to the output window is
Ctrl + Command + C``Space.
This is my most used command when writing Clojure in my day-to-day as the top-level form will work even for the simple examples that we tried earlier like
(+ 2 2), therefore it’s worth memorising the shortcut for it.
Running Clojure Tests
To run Clojure tests in Visual Studio Code, open a test file (e.g.
test/clojure_sandbox/core_test.clj and start typing
calva test into the Visual Studio Code command palette.
The four options:
- Run Tests
- Run Current Test
- Run Failing Tests again
- Run Tests for Current Namespace
Should be enough for you to fit into your testing workflow. See if you can make the test pass.
This is really just the beginning of your journey with Clojure and REPL driven development. I highly recommend the following next steps:
- Read the Calva documentation and refer to it when you need it.
- Memorise the Calva shortcuts for
Evaluate top level form.
- Follow all the exercises under the Learn Clojure official guide, using the sandbox project and REPL driven development for the exercises.
- Read the Leiningen documentation.
I hope this has been a useful primer to help you get going and focus on playing around with Clojure.