У меня есть такая карта (которая может быть вложена, используя обычные логические операторы, используя модуль «логический» и «данные» будут содержать соответствующие значения, такие как «влево», «вправо» и «оператор» будет "и", "или", "не"):
{ "data" { "name" "lang", "operator" "=", "value" "blue" },
"module" "impression_hint"}
Что мне нужно, так это функция, которая возвращает список, который можно интерполировать в (fn [context] ...) списке, где он сможет выполнять то, что мы к нему добавим.
Учитывая приведенную выше структуру, конечный результат после интерполяции в функцию должен выглядеть примерно так:
(fn [context]
(= ((context :impression_hint) "lang") "blue"))
Таким образом, моя функция синтаксического анализа / компиляции должна возвращать только часть (= ...). У меня есть нечто, что мучительно близко:
(defn- parse-internal [tree acc]
(cond
; other cases will go here
(= "impression_hint" (tree "module"))
(let [data (tree "data")
op (data "operator")
name (data "name")
value (data "value")]
`(~(symbol op) ((context :impression_hint) ~name) ~value))
:else
(throw (RuntimeException. (str "Unknown module: " (tree "module"))))))
В моем тесте это возвращает:
FAIL in (simple-shallow-rules-generate-simple-shallow-functions) (targeting.clj:10)
expected: (= (quote (= ((context :impression_hint) "name") "blue")) (bloom.adgear.targeting/parse {"data" {"name" "lang", "operator" "=", "value" "blue"}, "module" "impression_hint"}))
actual: (not (= (= ((context :impression_hint) "lang") "blue")
(= ((bloom.adgear.targeting/context :impression_hint) "lang") "blue")))
Обратите внимание на параметр контекста? Это было пространство имен, и это делает мой тест неудачным. Я уверен, что могу что-то сделать, но вызов символа приводит к тому, что символ не определен, что имеет смысл, поскольку символ еще не существует.
Относительно параметра acc: Я подозреваю, что со временем я удалю рекурсию из этой функции и повторю использование acc, передав мое возвращаемое значение на аккумулятор. Это немного дальше по дороге, хотя.