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

发布于 2024-10-08 09:52:43 字数 1503 浏览 0 评论 0原文

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

{ "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 进行递归,将我的返回值放入累加器中。不过,这还有些遥远。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

各自安好 2024-10-15 09:52:43

问题在于,语法引用形式(前面带有反引号)中的无命名空间文字符号会根据语法引用形式在词汇上出现的位置填充命名空间组件。您的问题似乎出现在定义 bloom.adgear.targeting 命名空间的文件中,因此这就是附加到 context 的内容。

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

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

波浪号取消引用下一个形式,因此它不受语法影响 -引用的魔力(包括自动解析符号);但随后它会被求值,因此需要引用,以便您返回原始形式(符号 foo),而不是它的值(无论 foo 当前绑定到什么)。

The problem is that namespace-less literal symbols in syntax-quoted forms (those preceded with a backtick) get the namespace component filled in based on where the syntax-quoted form lexically appears. Yours would appear to occur in the file where the bloom.adgear.targeting namespace is defined, so that's what gets attached to context.

Most of the time, this is a cool feature, but when you need to avoid it, you can use the ~' trick:

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

The tilde unquotes the next form, so it isn't affected by syntax-quote's magic (including autoresolving symbols); but then it gets evaluated, so the quote is needed so you get back your original form (the symbol foo) and not its value (whatever foo is bound to currently).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文