I have a map such as this (which can be nested using the usual boolean operators, using module "boolean" and "data" would contain appropriate values, such as "left", "right" and "operator" would be "and", "or", "not"):
{ "data" { "name" "lang", "operator" "=", "value" "blue" },
"module" "impression_hint"}
What I want is a function that returns a list which can be interpolated in a (fn [context] ...) list, where it will be able to execute against what we'll throw at it.
Given the above structure, the final result, after being interpolated into a function, should be something like this:
(fn [context]
(= ((context :impression_hint) "lang") "blue"))
Thus, my parsing/compiling function must only return the (= ...) part. I have something which is tantalizingly close:
(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"))))))
In my test, this returns:
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")))
Notice the context parameter? It's been namespaced, and this is what is making my test fail. I'm certain I can do something, but calling symbol results in a symbol not defined, which makes sense since the symbol doesn't exist yet.
Regarding the acc parameter: I suspect I'll remove recursion from this function, eventually, and recur using acc, cons'ing my return value onto the accumulator. That's a bit further down the road though.
symbol
function is meant to produce symbols which might not yet exist. Of course if the programme text reads(symbol foo)
, wherefoo
is a symbol, then it is the value offoo
which gets passed tosymbol
-- and iffoo
is unbound, an exception is thrown. In either case,foo
-the-symbol is created by the reader, so it exists since before the code is fed to the compiler. – Michał Marczyk