Sometimes one comments parts of code. Eg. to quickly check a different variant of the code. Or to return a mock value while debugging. Clojure provides several ways to comment code. Some more obvious than others...
The obvious way to add a comment is to use
;. It introduces a line
comment, that is the rest of the source code line is ignored. This is
nice to add „usual“ comments to source code. But temporarily commenting
code can be tedious.
(if (some-test) ; (production-code a b c) (temporary variant) (else-branch))
In this case it was easy. Just comment the whole line and everything
is fine. However what happens if we just want to comment
replace it with a different value? We have to break the line (or
and the closing paren will be ignored) or we have to copy the whole line
and take the above approach.
(if (some-test) ; (production-code a b c) (production-code a mock c) (else-branch))
Both approaches are not very compelling and involve a lot of ceremony to get the code correct again.
; is – let's say – suboptimal to comment code temporarily.
Another way to comment code is the
comment macro. However, this is
even less compelling than
;. There are some subtle issues. Who can
spot the bug (without entering things into a repl)?
(if (some-test) (comment (production-code a b c)) (temporary variant) (else-branch))
ticktackticktack beep As I said:
comment is a macro. Hence, it
has to evaluate to something. In case of
comment this something is
nil. So we have actually:
(if (some-test) nil (temporary variant) (else-branch))
if might complain. Other forms might not and happily go on with
now broken code (eg.
cond). For similar reasons, we cannot easily
b: it is replaced by
nil changing the function arguments.
Furthermore the contents of the macro must be valid code. In our
case this is true. But that means that
comment cannot be used for
arbitrary comments as with
(All in all, I don't see a reason, why one would ever want to use
comment besides wanting to comment several toplevel forms. But then
I can use
; just as well.)
So commenting out code for testing purposes seems to be pretty tedious
in Clojure. But wait! The reader to the rescue:
The reader features a reader macro, which drops the next thing read.
It is not replaced with
nil or whatever. It just reads the form from
the input and drops it under the table. The compiler actually never
sees the form. So we can write our initial example as:
(if (some-test) #_ (production-code a b c) (temporary variant) (else-branch))
In contrast to the
comment case this works as intended and we don't
have to fiddle with the parens. Similar, we can easily mock out
(if (some-test) (production-code a mock #_ b c) (else-branch))
We simply add our mock and ignore
b. And it doesn't matter whether
b is a symbol, a string or some arbitrarily complicated subform!
(if (some-test) (production-code a mock #_ (map (fn [x] (do-complicated-stuff x) (with even-more stuff)) (filter some-predicate? xs)) c) (else-branch))
But again: the thing following
#_ must be valid code. So no arbitrary
Beware the leopard!
#_ gives also an easy way to shoot one's foot!
(if (some-test) (production-code a #_ b c) (else-branch))
c is suddenly in the position of
There are several ways to „comment“ code.
; is the most straightforward
and behaves as you would expect from other languages.
however have some subtle gotchas, which one has to be aware of.
Nevertheless, at least
#_ is quite useful and should belong into
Published by Meikel Brandmeyer on .