Определить синоним макроса Clojure

Итак, следуя макрокоманде Clojure, чтобы создать синоним функции, я обнаружил, что def не может использоваться для определения синонима макроса. Ниже приведены примеры, которые я попробовал, чтобы Clojure не разрешал.

;(def def-function defn)
;(def case cond)
;(def function fn)

Можно ли определить синонимы/псевдонимы для макросов в Clojure? Требуется ли использование defmacro?

Ответ 1

Вы можете использовать макрос:

user=> (defmacro def-function [& args] `(defn [email protected]))
#'user/def-function
user=> (def-function g [] 2)
#'user/g
user=> (g)
2

Или вы можете использовать clojure.contrib.def/defalias:

user=> (use 'clojure.contrib.def)
nil
user=> (defalias def-function defn)
#'user/def-function
user=> (def-function g [] 2)
#'user/g
user=> (g)
2

Ответ 2

Может звучать (line-) шумно, но

(def #^{:macro true} case #'cond)

работает!

Ответ 3

Чтобы сделать это, по сути, вам нужно будет переписать макрос точно так же, как оригинал просто заменит другое имя (для этого вы, конечно, используете defmacro). Это единственный способ, который возможен, поскольку макросы не возвращают значение, а просто выписывают код, который должен быть впоследствии оценен.

Def требует привязки имени к значению, а не к блоку кода.

(def symbol init?)

Создает и ставит или находит глобальный var с именем символа и пространством имен значения текущего пространства имен (ns). Если задан init, он оценивается, и корневое связывание var устанавливается на результирующее значение. Если init не указан, корневое связывание var не изменяется. def всегда применяется к корневому связыванию, даже если var связан потоком в точке, где def вызывается. def дает сам var (а не его значение). Выдает исключение, если символ уже находится в пространстве имен и не сопоставляется с интернированным var.

из Clojure: специальные формы

Макросы не оценивают свои формы:

Макросы - это функции, которые манипулируют формами, допускающими синтаксическую абстракцию. Если оператор вызова является символом, который называет глобальную переменную var, которая является макрофункцией, эта макрофункция вызывается и передается неопубликованные формы операндов [italics mine]. Возвращаемое значение макроса затем оценивается на своем месте.

из Clojure: Оценка

В сумме точка макроса заключается в задержке оценки, поэтому она не может обеспечить значение для def для привязки к символу.