The flow
I jack into CIDER from permanent project files and use it to send
expressions to the REPL to be evaluated, with the results appearing
transiently right where I’m working. I almost never touch an actual
REPL. (This means I rely on the namespaces and aliases within each
namespace buffer, rather than explicit require
s in the REPL.) I do
this for both new functionality and debugging. This is by far the most
central aspect of my workflow: direct interaction with existing
project code, and evaluating progressive versions of new code directly
in the buffer where its final form will live.
When creating new functionality I start by sketching out the shape of
data I have and the shape of data I want to have. Usually this means a
concrete example (of both input and output) that I type out in data
literals or copy from some pre-existing source; occasionally it’s
enough to describe it with a comment. Often this dummy data takes the
places of what will become a parameter name. I start writing and
evaluating expressions on that dummy input, moving back and forth from
evaluating the top-level form and evaluating its sub-expressions.
I may spit REPL output as text directly into the buffer I’m working
with, so I can munge it or evaluate pieces of it. When working with
large results I make use of first
, take
, rand-nth
, and other
inspection functions, as well as intermediate def
s. If necessary, I
create an expression’s “state” by defining dummy vars like foo
or
xyz
in temporary def
s or let
s that get removed when cleaning up
a function for its final defn
ition.
As my code gets close to its final form, I save the examples I’m using
off somewhere else to become tests. This transition is one area where
my process is still loose. I also sometimes save nonce code or
potentially-reusable snippets to a project-specific repl.clj
namespace that I keep separate from source control and compilation.
After writing the function and its tests, it’s time for lein run
and
then lein test
for a double-check. I run those from the shell but
would like to experiment with running them from CIDER. In general I’m
trying to reduce the number of times that I run tests manually,
because they’re slow.
Important tools
Functionality I rely on in my Clojure environment, in approximate order:
- direct evaluation of expressions in permanent files
- Clojure indentation and syntax highlighting
- semantically-aware text selection (expand-region.el) and navigation (paredit)
- jump-to-definition (
cider-find-var
(M-.
) and returning withcider-pop-back
(M-,
)) - docstring hints (via eldoc.el plus CIDER)
I consider each one of those to be fundamental components for me to
achieve a Clojure-based flow state.
For a long time, docs and examples have been the one aspect of my
workflow that was strangely not on this list. Instead of getting
Clojure docs with emacs, usually I’d have a browser open to
clojuredocs.org. I’ve just recently started using cider-grimoire
(C-c C-d r
) for this purpose. I’d like to modify this part of my
workflow so that it looks things up locally instead of making an HTTP
request. (Down with 2-second delays!)
I look forward to hearing more folks share their development process