Почему 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 для того, чтобы съесть пирог и иметь его тоже.

Другие вопросы по тегам