exupero's blog
RSSApps

Stacking Clojure's "ignore next form" reader macro

Clojure provides a few bits of syntactic sugar via the dispatch macro #. When the parser sees a #, it changes behavior based on the next character, which provides Clojure with syntax for sets, regular expressions, and anonymous functions. One of my favorite dispatch macros is the "ignore next form" macro, #_, which skips the entire next form, not even emitting a nil value (as the comment macro does). I depend so much on the "ignore next form" macro in Clojure that I miss it in other languages. It feels tedious to identify which lines to comment out rather than just commenting out a single expression or statement.

One trick I learned from Twitter years ago, that I still use on a daily basis, is that sequences of #_ stack together. For example, #_#_ skips the next two forms:

[#_#_ 1 2 3]
[3]

Stacking works for any number of #_ reader macros. However many you put in a row, that many subsequent forms will be ignored by the reader.

Most times I stack #_ to skip a pair in a let binding, or to omit a key-value pair in a hash-map literal:

{:a 1 #_#_ :b 2 :c 3}
{:a 1, :c 3}
(macroexpand-1
  '(let [a 1
         #_#_
         b 2
         c 3]))
(let* [a 1 c 3])

With several forms to ignore, it's much easier to throw multiple #_ reader macros in one place than to prepend one #_ to each form I want to skip. I frequently use it with thread-first and thread-last macros (-> and ->>) to debug a series of transformations:

(->> (range 10)
     #_#_#_
     (map #(* 3 %))
     (filter even?)
     (map #(Math/pow % 2))
     (map #(/ % 2)))
(0 1/2 1 3/2 2 5/2 3 7/2 4 9/2)

Usually I only need to skip two or three forms, but a good Clojure syntax highlighter should style the forms being ignored as if they were comments, which helps track exactly which forms are ignored.