Макроэкспонирование после выражения (make-placeholders 9)
Я получаю это:
(for
[i__1862__auto__ (range 0 9)]
(defn-from
(str "_" i__1862__auto__)
{:placeholder true}
[& args]
(nth args i__1862__auto__)))
Так что defn-from
ожидает строку в качестве первого аргумента, но, поскольку это макрос, (str "_" i__1862__auto__)
не оценивается и, таким образом, вставляется в список.
Я какое-то время играл с этим и придумал:
(defmacro make-placeholders [n]
`(map eval
'~(for [cntr (range 0 n)]
`(defn ~(symbol (str "_" cntr))
{:placeholder true} [& args] (nth args ~cntr)))))
Макроэкспандирование (make-placeholders 3)
дает
(map eval
'((defn _0 {:placeholder true} [& args] (nth args 0))
(defn _1 {:placeholder true} [& args] (nth args 1))
(defn _2 {:placeholder true} [& args] (nth args 2))))
то, что я намеревался и оцениваю, определяет функции _0
, _1
и _2
:
;=> (_0 1 2 3)
1
;=> (_1 1 2 3)
2
;=> (_2 1 2 3)
3
Хорошо, это работает, но я все еще не уверен, что это хорошая идея.
Прежде всего Eval is evil . Хорошо, это также можно сделать без eval
, но с использованием do
(замените map eval
в моем решении на do
). Но вы, возможно, делаете свой код трудным для понимания, потому что вы создаете функции, которые не определены нигде в вашем коде. Я помню, что когда я только начал использовать Clojure, я искал какую-то библиотеку для функции и не мог ее найти. Я начал думать yikes, этот парень, должно быть, где-то определил макрос, который определяет функцию, которую я ищу, как я когда-нибудь пойму, что происходит? Если это то, как люди используют Clojure, то это будет чертовски бесполезно и затмит все, что люди говорят о Perl ... Оказалось, что я просто смотрю не на ту версию - но вы, возможно, настраиваете Вы и другие готовы к трудностям.
Сказав это, могут быть соответствующие применения для этого. Или вы можете использовать нечто подобное для генерации кода и поместить его в какой-то файл (тогда исходный код будет доступен для проверки). Может быть, кто-то более опытный может подключиться?