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 ifs to cohabit with a few lets 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.