В заключение, как мы можем применить и
или любой другой макрос к списку?
Это не работает:
(apply and '(true false))
Поскольку apply
не может принимать значение макроса.
Итак, как лучше всего проверить, все ли элементы списка верны?
В Clojure макросы не являются вещами первого класса , они не сочетаются совсем как функции, и вы не можете передать их другим функциям, и вы не можете apply
их. Это потому, что они закончены и завершены до того, как будет подано любое заявление.
Обычно заключают макросы в функции в apply
или передают их функциям
(defmacro my-macro [x y z] ...)
(apply #(my-macro %1 %2 %3) [1 2 3])
(map #(my-macro) [1 2 3] [:a :b :c] [a b c])
макрос чтения анонимных функций #(
делает это так Легко, что макросы, не будучи первоклассными, на самом деле не доставляют неудобств. Просто попробуйте запомнить первое правило макроклуба
user=> (eval `(and ~@(list true false)))
false
user=> (eval `(and ~@ (list true true 1)))
1
Я цитирую синтаксис, а затем применяю большую кувалду, чтобы убрать скобки вокруг коллекции, и, поскольку я цитировал ее, я должен использовать eval. Это полезно, если вы создаете макрос, а переданная функция - это 'and'.
Таким образом, (list 1 2 3)
кувалды становится 1 2 3
.
Это один из способов, чрезвычайно ужасный, но он работает, поэтому я понял, что для меня приятно. Так что мое замыкание не велико, но я надеюсь, что этот пример макроса прояснит ситуацию.
(defmacro split-my-args-then-apply-fn
"This is one terrible macro designed to show the use of 'and'."
[fun coll & args]
`(~fun ~@((apply juxt args) coll)))
Использование (никогда):
(split-my-args-then-apply-fn
and
{:something :true :something-else false}
:something :something-else)