2014-01-13 2 views
2

У меня проблема, когда я использую макросы в clojure. Вот что я пытаюсь сделать.Clojure: ошибка в макро. «Нет такого var»

(defmacro working-example [] 
    '(+ foo 1)) 

(defn working-function [foo] 
    (working-example)) 

(working-function 2) ; => 3 

(defmacro broken-example [bar] 
    `(+ foo ~bar)) 

(defn broken-function [foo] 
    (broken-example 1)) ; => I get error here. 

(broken-function 2) ; Should be 3. 

Я хочу, чтобы макрос сломанного примера заменял текст так же, как рабочий пример. Почему он не работает и как мне заставить его работать?

ответ

5

Я довольно новичок в Clojure, но я попытаюсь объяснить вам, что здесь происходит. Цитирование и обратная кавычка различаются в том, как они обрабатывают символы. Например, вы можете написать подобный код, который приведет к тонким различиям:

user=> '(+ foo 2) 
(+ foo 2) 
user=> `(+ foo 2) 
(clojure.core/+ user/foo 2) 

Обратите внимание, как только с помощью кавычки «связывает» символы в соответствующее пространство имен (clojure.core для + и user для foo). Напротив, цитирование просто рассматривает символ как есть. Если вы хотите, чтобы правильно написать сломанную функцию, вы можете использовать list синтаксис:

(defmacro broken-example [bar] 
    (list '+ 'foo bar)) 

(defn broken-function [foo] 
    (broken-example 1)) 

(broken-function 2) 

broken-function Теперь выдает ожидаемый результат.

EDIT:

Теперь благодаря А. Уэбб комментарий ниже, вы можете также избежать связывания с помощью этого синтаксиса пространства имен:

(defmacro broken-example [bar] 
    `(+ ~'foo ~bar)) 
+1

«Я знаю, что есть способ предотвращения обратного апострофа в найдите символ в пространстве имен "-' \ '(+ ~ 'foo 2)' –

+0

О, спасибо, А. Вебб. Я уточню сообщение для полноты. –

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