Почему eval работает там, где макрос не работает при построении условий WHERE в Корме
Я пытаюсь динамически добавлять условия WHERE в SQL-запрос Korma
(-> the-query
(where {:archived false})
(add-where-conditions params)
(limit 200)
(select))
Я пытаюсь динамически создать вызов функции korma's where. Звонок будет выглядеть примерно так (where query (or (between :freq [100 200]) (between :freq [300 400]) ... ))
, Вспомогательная функция make-conds создает список аргументов для функции where, например: (or (between :freq [100 200]) ...
Я попытался следующие подходы, чтобы построить динамический вызов. Только первый, тот, с eval
работает. Зачем? Есть лучший способ сделать это?
(defn add-where-conditions [query params]
(eval (list 'where query (make-conds params))))
(defmacro add-where-conditions-2 [query params]
(list 'where query (make-conds params))) ; broken
(defmacro add-where-conditions-3 [query params]
`(where ~query ~(make-conds params))) ; broken
Отказ от ответственности: я новичок в Clojure и Korma
1 ответ
Причина, по которой макросы не работают, состоит в том, что в обоих случаях значение для params
аргумент является символом params
, Вот почему в add-where-conditions-2
а также add-where-conditions-3
когда макросы делают вызов (make-conds params)
значение, которое получает функция - это не список, о котором вы думаете, а символ params
, показывая ошибку в строках:
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol clojure.lang.RT.seqFrom (RT.java:505)
Первый случай работает, потому что функция получает список (не символ) в качестве значения для params
аргумент, так eval
получает список (where {:your-query nil} (or (between :freq [100 200]) ,,,))
что является where
макрос ожидает и знает, как справиться.
where
макрос анализирует выражение в поисках некоторых предикатов, которые он использует для построения выражений. where*
альтернатива функции не имеет такой функциональности, поэтому я не могу придумать альтернативу eval
для того, чтобы съесть пирог и иметь его тоже.