I find myself using def in the middle of functions for exploring what is happening inside them, or what inputs they get. Here’s a somewhat (but not fully) contrieved example. I am trying to hook a React Native project on re-frame, and I have never used re-frame before. To learn what arguments are sent to the events, I use def to be able to use the REPL inside my editor to explore the inputs. The classic example is increasing a click-counter and this is my :inc-counter event:
It works, but before it worked I had to figure things out and instrumented the function like so:
Then, after clicking my Click me button. I could evaluate the forms and learn about what I was dealing with, like so:
As a beginner in Clojure land, I wonder if this is a ”dirty” way to do it and if I can expect problems doing things like this. It almost feels too easy, and I am trained by life to suspect too easy means I have to pay later in some way.
Cool! That works for some use cases, and is certainly a good tool.
However, it doesn’t help very much with interactively finding out the right body of code that will solve a task inside a function. By deffing the inputs like that I can build the function using the REPL from inside the function. A strong complement to using the REPL for testing the function from the outside.
Yes, it litters down the namespace in the running session, and that has bitten me at times. Tradeoffs, tradeoffs.
Some time ago I’ve stumbled upon the support library for this debugging technique: scope-capture. There is even a decent demo video. Back then it seemed really impressive, but I hadn’t have an opportunity to try it myself.
There is also another lib with a similar name: spy-scope. Among others it has a feature, similar to recently announced tap>.
I like to use the spy function from timbre, which logs its argument along with its name, and returns its argument. So you can use it to wrap any value or expression that you’re curious about and see it logged at runtime.
Admittedly that’s less interactive than your approach with def, but it has the advantage that you can keep such statements (within reason) in production code and just adjust the log level accordingly.