Построение списков в явном виде является «самым простым», в некотором смысле, потому что есть несколько основных концепций, которые вам нужно знать: просто примите список и измените его, пока у вас не появится новый список.Backtick - это удобный ярлык для «шаблонных» фрагментов кода;без него можно написать любой макрос, но для любого крупного макроса он быстро становится очень неприятным.Например, рассмотрим два способа записи let
в качестве макроса над fn
:
(defmacro let [bindings & body]
(let [names (take-nth 2 bindings)
vals (take-nth 2 (rest bindings))]
`((fn [~@names]
(do ~@body))
~@vals)))
(defmacro let [bindings & body]
(let [names (take-nth 2 bindings)
vals (take-nth 2 (rest bindings))]
(cons (list `fn (vec names) (cons `do body))
vals)))
. В первом случае использование backtick довольно ясно показывает, что вы пишете функцию имен, содержащихтело, а затем вызов его со значениями - код макроса «сформирован» так же, как и код расширения, так что вы можете представить, как он будет выглядеть.
Во втором случае, просто cons
и list
повсюду, очень сложно понять, как будет выглядеть расширение.Конечно, это не всегда так: иногда бывает проще написать что-то без обратной черты.
Еще один очень важный момент был сделан Кайлом Бертоном: print
- это не то же самое, что 'print
!Ваше расширение макроса должно содержать символ print
, а не его значение (которое является функцией).Встраивание объектов (таких как функции) в код очень хрупко и работает только случайно.Поэтому убедитесь, что ваши макросы расширены до кода, который вы могли бы написать сами, и позвольте системе оценки выполнить тяжелую работу - вы могли бы ввести символ print
, но вы не могли ввести указатель на текущее значениефункция print
.