在Clojure core.logic中,为什么我不能使用线程宏?

3
当我运行以下代码时,出现了下面的错误:
(run 3 [q]
  (fresh [a0 a1 a2
          b0 b1 b2
          c0 c1 c2]
    (== q [[a0 a1 a2] [b0 b1 b2] [c0 c1 c2]])
    (fd/in a0 a1 a2 b0 b1 b2 c0 c1 c2 (fd/interval 1 9))
    (fd/distinct [a0 a1 a2 b0 b1 b2 c0 c1 c2])
    (fd/eq
     (= a0 4)
     (= 22 (-  (* a0 a1) a2))
     (= -1 (-> b0 (* b1) (- b2)))
     )))

错误:

2. Unhandled clojure.lang.Compiler$CompilerException
   Error compiling src/euler/core.clj at (1392:5)

1. Caused by java.lang.IllegalArgumentException
   Can't call nil
 core.clj: 3081  clojure.core/eval
                  main.clj:  240  clojure.main/repl/read-eval-print/fn
                  main.clj:  240  clojure.main/repl/read-eval-print
                  main.clj:  258  clojure.main/repl/fn
                  main.clj:  258  clojure.main/repl
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  clojure.tools.nrepl.middleware.interruptible-eval/evaluate/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  630  clojure.core/apply
                  core.clj: 1868  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
...

注意带有线程宏->的那一行,在CIDER中我会对其进行宏展开,看起来一切都很好,但最终代码崩溃了。我认为这是宏的问题,但不确定原因。有什么想法吗?

1个回答

3
您应该查看clojure.core.logic.fd的源代码。错误发生在宏eq中,在宏展开之前,它会处理所有形式。
为了快速解决问题,我创建了一个版本的eq,它在执行任何其他操作之前对其所有形式调用macroexpand-all。它似乎适用于您的代码,但我没有在其他情况下进行测试:
(defmacro mac-eq [& forms]
  (let [exp-forms (map clojure.walk/macroexpand-all forms)]
    `(fd/eq ~@exp-forms)))

让我们试试吧!

stack-prj.logicThreadMacro> (run 3 [q]
                              (fresh [a0 a1 a2
                                      b0 b1 b2
                                      c0 c1 c2]
                                (== q [[a0 a1 a2] [b0 b1 b2] [c0 c1 c2]])
                                (fd/in a0 a1 a2 b0 b1 b2 c0 c1 c2 (fd/interval 1 9))
                                (fd/distinct [a0 a1 a2 b0 b1 b2 c0 c1 c2])
                                (mac-eq
                                 (= a0 4)
                                 (= 22 (- (* a0 a1) a2))
                                 (= -1 (-> b0 (* b1) (- b2))))))
()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接