When You Get to Be Smart Writing a Macro Day-to-day programming isn’t always exciting. Most of the code we write is pretty straightforward: open a file, apply a function, commit a transaction, send JSON. Finding a problem that can be solved not the hard way, but smart way, is quite rare. I’m really happy I found this one. I’ve been using hashp for debugging for a long time. Think of it as a better println. Instead of writing (println "x" x) you write #p x It returns the original value, is shorter to write, and doesn’t add an extra level of parentheses. All good. It even prints original form, so you know which value came from where. Under the hood, it’s basically: (defn hashp [form] `(let [res# ~form] (println '~form res#) res#)) Nothing mind-blowing. It behaves like a macro but is substituted through a reader tag, so defn instead of defmacro. Okay. Now for the fun stuff. What happens if I add it to a thread-first macro? Nothing good: user=> (-> 1 inc inc #p (* 10) inc inc) Syntax error macroexpanding clojure.core/let at (REPL:1:1). (inc (inc 1)) - failed: vector? at: [:bindings] spec: :clojure.core.specs.alpha/bindings Makes sense. Reader tags are expanded first, so it replaced inc with (let [...] ...) and then tried to do threading. Wouldn’t fly. We can invent a macro that would work, though: (defn p->-impl [first-arg form fn & args] (let [res (apply fn first-arg args)] (println "#p->" form "=>" res) res)) (defn p-> [form] (list* 'p->-impl (list 'quote form) form)) (set! *data-readers* (assoc *data-readers* 'p-> #'p->)) Then it will expand to user=> '(-> 1 inc inc #p-> (* 10) inc inc) (-> 1 inc inc (p->-impl '(* 10) * 10) inc inc) and, ultimately, work: user=> (-> 1 inc inc #p-> (* 10) inc inc) #p-> (* 10) => 30 32 Problem? It’s a different macro. We’ll need another one for ->>, too, so three in total. Can we make just one instead? Turns out you can! Trick is to use a probe. We produce an anonymous function with two arguments. Then we call it in place with one argu...
First seen: 2025-10-23 05:29
Last seen: 2025-10-23 15:31