Skip to content

Essential tooling for Clojure development

alternative text

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λ︎

Practicalli Clojure REPL concept logo

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.

clojure -M:repl/rebel

Practicalli Rebel Readline rich terminal REPL

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

Practicalli Clojure REPL Workflow

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

Practicalli Clojure REPL connected editor

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.

Parinfer example

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λ︎

Practicalli Portal data inspector logo

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.

🌐 Practical.li Website

Practical.li GitHub Org practicalli-johnny profile

@practicalli@clj.social @practical_li