Compiler construction 测试将结构编译为类似于列表的函数的高阶函数

Compiler construction 测试将结构编译为类似于列表的函数的高阶函数,compiler-construction,clojure,higher-order-functions,Compiler Construction,Clojure,Higher Order Functions,我有一个这样的映射(可以使用常用的布尔运算符嵌套,使用模块“boolean”和“data”将包含适当的值,例如“left”、“right”和“operator”将是“and”、“or”、“not”): 我想要的是一个函数,它返回一个可以插入(fn[context]…)列表中的列表,在这个列表中,它将能够针对我们将抛出的内容执行 根据上述结构,插值到函数后的最终结果应如下所示: (fn [context] (= ((context :impression_hint) "lang") "bl

我有一个这样的映射(可以使用常用的布尔运算符嵌套,使用模块“boolean”和“data”将包含适当的值,例如“left”、“right”和“operator”将是“and”、“or”、“not”):

我想要的是一个函数,它返回一个可以插入(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进行递归,将返回值保存到累加器上。问题是,在语法引用形式(前面带有倒勾的形式)中,没有名称空间的文字符号会根据语法引用形式在词汇上出现的位置填充名称空间组件。您的出现在定义了
bloom.adgear.targeting
名称空间的文件中,因此这就是附加到
context
的内容

大多数情况下,这是一个很酷的功能,但是当您需要避免它时,您可以使用
~”
技巧:

`foo
; => some-ns/foo
`~'foo
; => foo

tilde取消引用下一个表单,因此它不受syntax quote的魔力(包括自动还原符号)的影响;但随后它会被评估,因此需要引用,这样您就可以返回原始形式(符号
foo
),而不是它的值(无论当前绑定的是什么)。

关于上面倒数第二段的一个小注释。实际上,
symbol
函数用于生成可能还不存在的符号。当然,如果程序文本读取
(symbol foo)
,其中
foo
是一个符号,则传递给
symbol
的是
foo
的值,如果
foo
未绑定,则引发异常。在任何一种情况下,
foo
-符号都是由读取器创建的,因此它在代码馈送到编译器之前就存在了。
`foo
; => some-ns/foo
`~'foo
; => foo