Search code examples
clojuremacros

Clojure: Take a macro metadata inside another macro


On one of my pet projects I have a bunch of macros, and sometimes I want to be able to read metadata from macro definition. The reason being that sometimes my other macros should expand differently depending on input form. Of course, it is rather simpler to just expand and then read metadata, but I wonder if it's possible to do while macro is expanding.

Consider following macro:

(defmacro stackoverflow 
  {:example 23} 
  [& args] 
  (comment "This is just an example"))

It is perfectly simple to read metadata from macro in regular function.

(defn- -example?
  [form-var]
  (-> form-var
      meta
      :example
      some?))

:=> (-example? #'stackoverflow)
true

It is not hard to do inside another macro as well:

(defmacro example?-macro[form] 
  `(-example? (var ~form)))

:=> (example?-macro stackoverflow)
true

But I couldn't find a way to get meta while macro is expanding:

(defmacro test-example? [form]
  (if (example?-macro form)
    (println "It is indeed an example")
    (println "It is not and example!")))

> Unable to resolve var: form in this context

I want my test-example? to do different job depending on the input form, but couldn't find a way to do it.

In short the whole question boils to: How to take var from input macro inside macro without expanding like so:

;; This is desired behaviour

(defmacro imagining-solution
  [form]
  (if (:example `(meta (var ~form)))
    (println "It is indeed an example")
    (println "It is not and example!")))

;; But one can only dream about

Solution

  • Immediately after posting this question ;) found a solution here: Accessing argument's metadata in Clojure macro

    Just use resolve function!