2014-09-30 10 views
3

У меня есть вопрос о некотором кодексе в библиотеке compojure Clojure.Функции Clojure и gensym

(defn compile-route 
    "Compile a route in the form (method path & body) into a function." 
    [method route bindings body] 
    `(make-route 
    ~method ~(prepare-route route) 
    (fn [request#] 
     (let-request [~bindings request#] [email protected])))) 

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

Я бы подумал, что, поскольку выше это функция, а не макрос, он невосприимчив к этому. Поэтому мне интересно, какое обоснование для написания этой функции, как макроса.

(В случае, если вам интересно, я проверил совершить историю, чтобы увидеть, если эта функция была изначально написана как макрос. Это не было.)

ответ

3

Хотя вы видите функцию, а не макрос, это функция, которую генерирует код Clojure. (Это почти наверняка будет вызвано из макроса.) И, он не только генерирует код, но и вставляет код, который передается в качестве аргумента body в сгенерированный код. Вот почему нужно избегать конфликтов имен.

Хотя это не макрос, он делает то же самое, что и макросы, и использует gensym по той же причине.

5

Gensyms (-# обозначения по крайней мере), используются не в контекст макросов, но в контексте backquote. Чтобы более или менее обеспечить macro hygiene, символы, которые не разрешают глобально квалифицированные символы, не могут использоваться внутри контекста backquote. Хотя это не применяется, и есть побег, если вы действительно хотите неквалифицированный символ, он обеспечивает нормальную по умолчанию. Для более продолжительного обсуждения макрогигиены в Clojure см. this сообщение в блоге.

Смежные вопросы