我有一个这样的地图(可以使用通常的布尔运算符嵌套,使用模块“布尔”和“数据”将包含适当的值,例如“左”、“右”和“运算符”将是“和” , “或不”):
{ "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")))
注意上下文参数?它已被命名空间,这就是我的测试失败的原因。我确定我可以做某事,但是调用 symbol 会导致符号未定义,这是有道理的,因为该符号尚不存在。
关于 acc 参数:我怀疑我最终会从此函数中删除递归,并使用 acc 进行递归,将我的返回值放到累加器上。不过,这有点远。