WTF does #+(or)
mean?
They’re called reader macros. Reader macros in Common Lisp are a read-time
feature that lets you do a pre-compile condition check. The #+
reader
macro checks
for a feature, and if it succeeds, then the S expression following it is
evaluated. If not, the code never even gets passed to the compiler. It is as
if it never existed. They’re kinda like the ifdef
and ifndef
macros in
C/C++. They’re there to let you define an expression if a feature exists.
Why would I ever do that?
Let’s say you want to do something only if the quicklisp feature is present.
Rather than writing a function that looks at *features*
to see if :QUICKLISP
is in the feature list, and having that check compiled into your code and
running every time you run your code, you could do something like this:
|
|
If quicklisp is in *features*
then do-something-with-quicklisp
gets handed
to the compiler. If not, none of that code ever even makes it to the compiler.
It’s filtered out when the file is read, hence the name.
Okay, the question remains, what is the #+(or)
?
I use it to get the same functionality that one might get from the
ignore syntax: #_
in Clojure. It
checks the condition (or)
, which, with no arguments, will always return NIL.
It’s a condition that can never pass, so the expression immediately following it
will never make it to the compiled output in real life. It will never exist in
your shipped binary, but you can evaluate the expression in your repl all day.
It’s nice if you’re doing REPL dev in your editor and add some function to mess
with something that should never exist in the final product. I leave them in my
code if I need to mess with something from time-to-time (external api call
behavior checks, etc.). Here’s an example.
|
|
- The
try-broke-ass-thing
function is a function I might write to target thebroke-ass-thing
function. - The
broke-ass-thing
is misbehaving or needs some love in some way. Maybe it’s calling an API for which I am trying to figure out the response shape or something.
I can load the whole file into my repl and manually evaluate
try-broke-ass-thing
as I tweak the code. When I finish tweaking, I can leave
the definitions. If I ever need to use those again, they’re there, but they
never ship with the final binary.
Is it a hack? Probably. Would tests be better? Yes. Will I keep doing this? Absolutely, when I need something quick and dirty.