Оригинальный ответ
Я думаю, это то, что вы ищете:
(defmacro is [expr value]
`(if (= ~expr ~value)
true
(println "Expected " ~value "In" (str (quote ~expr))
"But Evaluated to" ~expr)))
то, что делает (quote ~expr)
, - это перенос s-выражения, представленного expr
, в ваш «шаблон», но предотвращает его оценку, а затем применение str
к неоцененному s-выражению превращает его в строку для объединения с другими строками сообщения об ошибке. Итак:
user=> (is (+ 2 2) 5)
Expected 5 In (+ 2 2) But Evaluated to 4
производит желаемое поведение.
Вместо того, чтобы использовать 'yes
для сообщения об успехе, вы можете просто использовать true
в качестве отчета об успешном прохождении теста, давая:
user=> (is (+ 2 2) 4)
true
и избежание проблемы возврата 'yes
в качестве квалифицированного символа. Если по какой-то причине вам нужен символ, вы можете сделать ключевое слово:
(defmacro is [expr value]
`(if (= ~expr ~value)
:yes
(println "Expected " ~value "In" (str (quote ~expr))
"But Evaluated to" ~expr)))
user=> (is (+ 2 2) 4)
:yes
Ответ на вопрос, заданный в комментариях
Вы спрашивали в комментариях:
Извините, я должен был быть более ясным в своем вопросе. Какая разница между символом и ключевым словом в этом случае?
Рассмотрим исходное определение (с исправлением, чтобы ошибка возвращалась так, как вы хотели):
(defmacro is [expr value]
`(if (= ~expr ~value)
'yes
(println "Expected " ~value "In" (str (quote ~expr))
"But Evaluated to" ~expr)))
Я полагаю, что вы хотите, чтобы 'yes
думал, что вы можете использовать его для тестирования против 'yes
в других контекстах (такие тесты часто встречаются во вводных текстах для lisp). Но 'yes
используется в вашем определении макроса, он возвращает квалифицированный символ при прохождении теста:
user=> (is (+ 2 2) 4)
user/yes
Так вот, это не то, что вы хотели бы. Представь, что ты сказал это:
user=> (= 'yes (is (+ 2 2) 4))
false
Чтобы получить true
ответ, вы должны будете сказать это (используя синтаксическую кавычку):
user=> (= `yes (is (+ 2 2) 4))
true
Если вы определили свой макрос для возврата :yes
, то вы получите возврат, который можно проверить, без необходимости синтаксического цитирования объекта, который вы используете для проверки:
user=> (= :yes (is (+ 2 2) 4))
true
Но это все излишне, потому что вас действительно интересует, вернет ли (+ 2 2)
4
, т. Е. Является ли ваше утверждение true
или false
, а не равно, равно ли 'yes
`` yes or
'yes ; you can just have it return
true` и избегайте этого шага проверки (в реальном мире).
В любом случае, чтобы понять, что такое квалифицированные символы, вам нужно прочитать документы на считывателе clojure и этот ответ SO, объясняющий входы и выходы символов в clojure .