0

我有一个这样的地图(可以使用通常的布尔运算符嵌套,使用模块“布尔”和“数据”将包含适当的值,例如“左”、“右”和“运算符”将是“和” , “或不”):

{ "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 进行递归,将我的返回值放到累加器上。不过,这有点远。

4

1 回答 1

1

问题在于,语法引用形式(以反引号开头)中的无命名空间文字符号会根据语法引用形式词法出现的位置来填充命名空间组件。你的似乎出现在bloom.adgear.targeting定义命名空间的文件中,所以这就是附加到context.

大多数时候,这是一个很酷的功能,但是当你需要避免它时,你可以使用这个~'技巧:

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

波浪号取消对下一个形式的引用,因此它不受语法引用的魔力(包括自动解析符号)的影响;但随后它会被评估,因此需要引用,以便您取回原始形式(符号foo)而不是其值(foo当前绑定的任何内容)。

于 2010-12-18T21:58:07.180 回答