В Clojure вам нужно использовать gensym
для создания символов для внутреннего использования в ваших макросах, чтобы поддерживать их гигиеничность. Однако иногда вам нужно использовать один и тот же символ во вложенных синтаксических кавычках. Например, если я хочу привязать значение к символу с помощью let
и напечатать его три раза в развернутом цикле, я бы сделал
`(let [x# 1]
[email protected](repeat 3
`(println x#)))
Но это создаст
(clojure.core/let [x__2__auto__ 1]
(clojure.core/println x__1__auto__)
(clojure.core/println x__1__auto__)
(clojure.core/println x__1__auto__))
x#
генерирует другой символ в форме let
, чем в формах println
, вложенных в него, потому что они были созданы из разных синтаксических кавычек.
Чтобы решить эту проблему, я могу заранее создать символ и ввести его в синтаксические кавычки:
(let [x (gensym)]
`(let [~x 1]
[email protected](repeat 3
`(println ~x)))
)
Это приведет к правильному результату с тем же символом, который необходим везде:
(clojure.core/let [G__7 1]
(clojure.core/println G__7)
(clojure.core/println G__7)
(clojure.core/println G__7))
Теперь, когда он дает правильный результат, сам код выглядит уродливым и подробным. Мне не нравится, когда нужно "объявить" символ, и синтаксис инъекции делает его похожим на то, что он появился вне макроса или вычислялся где-то внутри него. Я хочу иметь возможность использовать синтаксис auto-gensym, который дает понять, что это макро-внутренние символы.
Итак, есть ли способ использовать auto-gensym с вложенными синтаксическими кавычками и заставить их выдавать один и тот же символ?