Essential tooling for Clojure development
Clojure development benefits from great tooling focused around an editor.
Autocomplete, refactor tools, diagnostics feedback and syntax highlighting enhance the creation and modification of code.
Evaluating in source code and using data inspectors for the results provides an effective interaction with the REPL.
Practicalli encourages editors that provide user actions driven exclusively via the keyboard and an uncluttered user interface.
Practicalli Clojure provides an overview of Clojure editors and the plugins that provide Clojure support, e.g. Emacs, Neovim, VS Code, Pulsar and Sublime.
Practicalli preferred editors
LightTable was the editor used in the early years of learning Clojure as it was simple to use and provided instant feedback as code was typed.
Once Spacemacs was release, Emacs with CIDER became the predominant editor for many years.
Treemacs and LSP have matured so Neovim and Conjure has been adopted to provide a fast editing environment with streamlined key bindings for Clojure development.
REPL connnectionλ︎
Interaction with the REPL is the foundation of highly effective Clojure development. An editor connects to a REPL process via a network repl (nREPL) server process.
Practicalli starts a REPL process in a terminal using the Clojure CLI tool.
:repl/rebel
alias is used to run Rebel Readline to provide a rich terminal UI REPL prompt and starts an nREPL server to support an editor connection.
Jack-in or Connect
The REPL and nREPL processes are started by an editor jack-in command, providing the relevant dependencies and command line options to the Clojure CLI. The editor automatically connects to the nREPL process.
The same command can be run in a terminal and once nREPL server is running the editor can be connected.
Practicalli uses a terminal REPL prompt for longer running processes or as a way to separate logs from evaluation events, e.g. starting components such as web servers.
Starting the REPL process outside of the editor provides a useful separation of editor and REPL, also allows for a range of editors and other tooling to share the REPL state
Customise REPL starupλ︎
The user
namespace is always loaded during REPL startup, allowing tools and libraries to be included via a user.clj
file when on the class path.
Clojure development workflows and tools may vary across projects, so customising the REPL starup is highly valuable.
Aliases for development tools
Clojure CLI aliases from project and user level deps.edn to support different configurations and tools when starting the REPL process
The :dev/env
and :repl/reloaded
aliases from Practicalli Clojure CLI Config add the dev
directory to the class path, loading a custom user
namespace defined in dev/user.clj
.
A custom user
namespace supports the Practicalli REPL Reloaded workflow, launching Portal data inspector listening to all evaluation results and Mulog Tap Publisher sending log events to Portal.
Evaluate Clojureλ︎
Evaluates expressions as they are written, providing qualative feedback on the expected behaviour.
Expressions are evaluated in Source code window with results inline, keeping focus on the code and avoiding the need to switch namespaces in the REPL. Larger data structures can be sent to a data inspector (Portal, Cider Inspector)
Cleaning up the REPL state
- Un-evaluate a var to avoid running stale code and tests, e.g. remove def, defn, deftest names from the REPL process
Structural Editingλ︎
Clojure has a highly structured syntax compared to many other languages thanks to its LISP heritage. Functions are defined and called in expressions using parenthesis, ()
.
Writing and code refactor is enhanced when the editor ensures parenthesis remain balanced, i.e. every opening paren has a closing paren.
paredit ensurce balanced parens along with structural refactor commands to change the structure, e.g.
- slurp pulls expressions into the current expression
- barf pushes the current expression out of the surrounding expression
parinfer provides structural editing based on indentation, automatically ensuring parens are ballanced as code is added or changed. Parinfer doesnt require any commands or key bindings and so can feel more natural.
Maintain REPL Stateλ︎
A Clojure REPL can be very long lived thanks to the stability of the Java Virtual Machine (JVM). Removing state vars can help avoid a REPL restart, as tools that refresh namespaces and start/stop/restart a Clojure system components.
- refresh changed namespaces of the project in the REPL process, optionally with hook to restart components
For simpler applications, Practicalli loads clojure.tools.namespace.repl
at REPL starup via a custom user
namespace to refresh
stale namespaces in the project and set-refresh-dirs
to define the directory paths that should be checked for changes (excluding dev
from the path to avoid reloading tools).
For web services and Clojure projects composed of system components, the Practicalli Service REPL workflow is used. The Service REPL workflow uses either donut-party/system or Integrant & Integrant REPL to manage restarting of components and reloading changed namespaces into the REPL state.
Practicalli Service REPL workflow
donut-party/system Integrant & Integrant REPL
Inspecting / Navigating Dataλ︎
Many results of evaluating Clojure produce interesting and potentially complex data structures. Tools for navigating data aid in the understanding of results produced by Clojure code.
Being able to present the results in different ways can add greater meaning and easier consumption of the results, e.g. visual charts to support data science.
- navigate data, especially nested data
- paginate through large data sets without slowing down the tooling
- inspect results of an evaluation and follow updates after each evaluation
Emacs Cider Inspector is very powerful for paging through large data sets effectively and navigating a complex structure.
Portal can also navigate data and can show data in a range of views to add more meaning support, e.g. http responses for API development, tables & charts for data science, etc...
Practicalli configures Portal to listen over nREPL to all Clojure code evaluations, which will work with all of the Clojure editors.
Portal Data Inspector - Practicalli Clojure
Creating projectsλ︎
Creating a a clojure project from templates can save time and provide a consistent base for an organisation. Extending project templates with options allows for diversity whist still providing common a approach.
Projects from template are typically created via a shell command, so an editor with shell support is valuable.
Practicalli Project Templates simplifies Clojure project creation with a growing number of templates, derived from commercial and community experiences.
Thank you.