Writing Code That Writes Code for You
Web Development with Clojure, Third Edition — by Dmitri Sotnikov, Scot Brown (80 / 107)
👈 What About Global State? | TOC | The Re ad-Evaluate-Print Loop 👉
Because Clojure is a dialect of Lisp, it provides a powerful macro system. Macros allow for templating of repetitive blocks of code and for deferring evaluation, among numerous other uses. A macro works by treating code as data instead of evaluating it. This allows us to manipulate the code tree just like any other data structure.
Macros execute before compile time, and the compiler sees the result of macro execution. Because of this level of indirection, macros can be difficult to reason about, and thus it’s best not to use them when a function will do the job.
However, macros have legitimate uses, and it’s worth understanding how they work. In this book we use very few macros, so we’ll only touch on their syntax superficially.
Let’s look at a concrete example of a macro and see how it differs from the regular code we saw previously. Imagine that we have a web application with a session atom that might contain a user. We might want to load certain content only if a user is present in the session and not otherwise.
(def session (atom {:user "Bob"}))
(defn load-content []
(if (:user @session)
"Welcome back!"
"please log in"))