Can you elaborate?
Yes, but notice this line:
(. (var defmacro) (setMacro))
Which will notify the compiler to treat defmacro
as a Macro, and therefore it will be macro-expanded at compile-time (with no runtime penalty).
More info:
There are many surprising uses to macros. One of them is splitting code. Imagine
(let [that (we-have)
several (elements)
of (computation)
layed-out (as such)
in (a let)]
...)
Let’s suppose we also want to perform a series of operations tangentially to the sequence of computations above, for instance to do some logging. We might end up with something like this.
(let [that (we-have)
_ (log that)
several (elements)
_ (log several)
of (computation)
_ (log of)
layed-out (as such)
_ (log layed-out)
in (a let)
_ (log in)]
...)
To preserve readability by separating orthogonal sides of code we can manage something like this.
(defmacro with-logging [[_let bindings]
`(let ~(add-logging bindings)))
(with-logging
(let [that (we-have)
several (elements)
of (computation)
layed-out (as such)
in (a let)]
...)))
What’s nice is that instead of refactoring the initial let into a new abstraction like functions that compose monadically, I can stick to my code and let the refactoring be done by a macro in terms common to all these competing abstractions: in Clojure like in all lisps, inert code is just nested lists of symbols.
Also they can be very short and powerful. I wrote this one out of frustration fighting multiple levels of if
s to cohabit with a few let
s and decided to flatten it all.
;; Goal: a macro similar to `let` that evaluates its bindings lazily.
(require '[clojure.tools.macro :refer [symbol-macrolet]])
(defmacro lay [[sym expr & more-bindings] & body]
(let [delay-sym (gensym (str "laid-" sym "-"))]
`(let [~delay-sym (delay ~expr)]
(symbol-macrolet [~sym (deref ~delay-sym)]
~@(if (empty? more-bindings)
body
`[(lay ~more-bindings ~@body)])))))
;; Simple example
(defmacro lay-it [& body]
`(lay [~'a (print "a")
~'b (print "b")
~'c (do ~'b (print "c"))]
~@body
(newline)))
(lay-it a) ;; a
(lay-it b) ;; b
(lay-it a b) ;; ab
(lay-it b a) ;; ba
(lay-it c) ;; bc
(lay-it c a) ;; bca
(lay-it c b a) ;; bca (no re-evaluation, uses cached result instead)
This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.