Почему clojure добавляет к именам внутри обратной кавычки квалификаторы пространства имен?

Я пытаюсь создавать запросы журнала данных программно, но продолжаю сталкиваться с проблемой, которую я проиллюстрирую на примере функции:

(defn test-expr [attribute]
  `[?entity ~attribute ?value]])

Когда я запускаю (test-expr 3), я ожидаю вывод:

 [?entity 3 ?value]

Но вместо этого я получаю

[mynamespace/?entity 3 mynamespace/?value]

Чего я явно не хочу. Есть ли способ сказать clojure: «Пожалуйста, просто процитируйте список и разверните переменные, которые я вам говорю?»


person TG-T    schedule 07.12.2012    source источник
comment
Что касается причины, то она заключается в том, чтобы пользователи (кашель) не могли случайно нарушить ваши макросы, определив функции и/или переменные с тем же именем, которое вы используете.   -  person Cubic    schedule 07.12.2012
comment
@Cubic, согласен. Насколько я понимаю, это своего рода компромисс между гигиеническими макросами Scheme и простыми макросистемами Common Lisp: определения макросов выглядят почти точно так же, как Common Lisp (это хорошо, так как макросы Scheme сложнее писать IMO), но по умолчанию присутствует определенный уровень гигиены - символы не захватываются вслепую, а вместо этого имеют префикс пространства имен. И всегда можно вернуться к простым заменам, когда это необходимо (например, для анафорических макросов).   -  person Vladimir Matveev    schedule 07.12.2012


Ответы (2)


Да, есть.

(defn test-expr [attribute]
  `[~'?entity ~attribute ~'?value])

Здесь вы сначала раскачиваете синтаксическую цитату, а затем сразу же снова заключаете в кавычки символ (конструкция ~'). Результатом является символ без пространства имен.

Это эквивалентно следующему, что объясняет, как это работает:

(defn test-expr [attribute]
  `[~(quote ?entity) ~attribute ~(quote ?value)])
person Vladimir Matveev    schedule 07.12.2012

Что вам нужно, так это библиотека backtick от Brandon Bloom https://github.com/brandonbloom/backtick

Он был построен именно для проблемы, которую вы описываете. Он предоставляет команду с именем «шаблон», которая работает как обратная кавычка, но без пространства имен.

В Clojure квазицитирование и разрешение пространства имен объединены в одной функции. Это дает большие преимущества при написании макросов на таком языке, как Clojure, который является «Lisp-1» (в отличие от Common Lisp, который является «Lisp-2» с отдельными пространствами имен для функций и переменных).

Я также согласен с тем, что, возможно, было бы лучше не объединять эти функции, но это сделало бы написание макросов в Clojure менее элегантным, поэтому я понимаю, почему это работает именно так.

person drcode    schedule 07.12.2012