Clojure beginners often hear that inline
def is bad style. For code
you commit that’s mostly true. Example:
1 2 3
def performs a side effect every time you call
y which is global to the current
namespace. Instead you should use
let to make it a local:
1 2 3
defs can serve a useful purpose, namely that of a
simple debugger. Debuggers for Clojure exist, e.g. in CIDER, but I
mostly forget to use them. After
def is my
debugging tool of choice.
How should I call this function? Of course.
Wait, what? Inline
def to the rescue.
1 2 3 4 5 6 7
Oh, of course! What happened is that
m was bound to the first
argument. I get it, I should have called
foo like this:
Time to remove the inline
def and get on with life.
I regularly use this technique to capture input that is part of some processing chain and I’m not sure what data is flowing through, or when the input is hard to simulate from the REPL, e.g. coming form a large HTTP request body. Recently I was working on some XML parsing. For every XML file this function was called:
1 2 3 4
That function was part of larger flow that reads from a directory of
zipfiles containing XML files. After processing a few files I would
get an exception. Let’s inspect
xml-as-str, the last input that
triggered the exception.
So the last entry from the zipfile was empty. Turns out the entry was
not an XML file, but a directory represented by an empty
string. Another example involved some XML file that didn’t have the
format I expected. Every time I got a new exception I could quickly
see what was going on and retry
without kicking off the flow from scratch.
Next time you have the urge to reach for a debugger, you might want to
become friends with inline
Creating temporary vars with the same name as function arguments has the added benefit of being able to evaluate expressions within your function. This is discussed the blogpost REPL Debugging: no stacktrace required by Stuart Halloway.