3

I've defined a macro in func.clj:

(ns my-library.func)

(defmacro my-macro [arg]
  `(identity ~arg))

and I want to bind it to a variable in core.clj:

(ns my-library.core
  (:require [my-library.func :as func])

(def my-macro-core func/my-macro)

so that I can do something like the following:

(ns script.core
  (:require [my-library.core :as mlc]))

(mlc/my-macro-core :boring-macro) ; -> :boring-macro

However, I can't do that because macros don't evaluate to a value. The following works:

(ns my-library.core
  (:require [my-library.func :as func])

(defmacro my-macro-core [arg]
  `(func/my-macro ~arg))

but it's redundant, so I was wondering if there's a cleaner way to do this.

2 Answers 2

2

It's a bit of a hack, but it can be done:

(ns my-library.func)

(defmacro my-macro [arg]
  `(identity ~arg))

(ns my-library.core
  (:require [my-library.func :as func]))

(def ^:macro my-macro-core @#'func/my-macro)

(ns script.core
  (:require [my-library.core :as mlc]))

(mlc/my-macro-core :boring-macro)

The trick is to set the new var being defined to the raw function value of the macro being aliased, while setting the :macro metadata flag so the compiler recognizes it and calls it appropriately.

Sign up to request clarification or add additional context in comments.

2 Comments

It seems that the @ is unnecessary. For example, (def ^:macro my-or #'or) yields a new macro my-or which works exactly like or. What is that? Thanks for the answer again.
The way I posted just avoids Var indirection. Using the var itself is useful if you want subsequent updates to the var's value to be reflected in aliases.
0

Potemkin's import-vars supports macros:

(require '[potemkin :refer [import-vars]])
(import-vars [my-library.core my-macro])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.