【问题标题】:Generate core.logic statements using macros使用宏生成 core.logic 语句
【发布时间】:2015-04-21 08:36:27
【问题描述】:

我正在尝试通过“填空”动态构建 core.logic 语句。这是一个简单的例子:

(def number 42)
(def stmt `(run* [q] (== q ~number))
(eval stmt)

但是我得到了clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: No such var: user/q, compiling:(null:20:12)

我已经尝试了引用、取消引用和取消引用拼接的所有组合,但我无法弄清楚。我应该如何插入q

(并且,退一步,建立这样的陈述是正确的方式吗?)

【问题讨论】:

    标签: clojure clojure-core.logic


    【解决方案1】:

    由于您使用的是语法引用,因此符号 q 在当前命名空间中被引用。

    引用它是不合格的,但不引用它而不是语法引用引用本身:

    (def stmt `(run* [~'q] (== ~'q ~number)))
    

    或者生成一个符号

    (def stmt `(run* [q#] (== q# ~number)))
    

    【讨论】:

    • q# 符号生成似乎是要走的路,因为它比未引用的 ~'q 看起来更容易混淆。
    • e. 也更卫生。 G。 number 是一个带有不同 q 的表单。
    【解决方案2】:

    如果您的逻辑语句存储为字符串,您可以使用read-string 来获得Clojure 表单,然后在其上调用eval

    (def number 42)
    (def stmt-as-str "(run* [q] (== q number))")
    (eval (read-string stmt-as-str))
    > (42)
    

    或者,如果它只是一个表格:

    (def stmt-as-form '(run* [q] (== q number)))
    (eval stmt-as-form)
    > (42)
    

    注意:`~~@ 通常用于宏定义。

    【讨论】:

    • read-string 违背了使用 Clojure 数据结构的目的。我需要在 run* 宏中取消引用拼接更复杂操作的宏功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多