6

我一直在使用 Clojure.logic 完成The Reasoned Schemer (TRS),并注意此处记录的差异。我到达第 3 章的第 24 帧,TRS 报告说

(run 5 [x]
  (lolo '((a b) (c d) . x)))

应该产生

'(()
  (())
  (() ())
  (() () ())
  (() () () ())

现在,我实现了`lolo as

(defn lolo
  "Succeeds if l is a list-of-lists."
  [l]
  (conde
   ((emptyo l) s#)
   ((fresh [a]
           (firsto l a)
           (listo a)) (fresh [d]
                             (resto l d)
                             (lolo d)))
   (s# u#)))

这会产生以下奇怪的结果:

'(()
  (())
  ((_0))
  (() ())
  ((_0 _1)))

这基本上意味着我的 lolo 正在产生泄漏出新变量的解决方案。如果我继续前进,试图看到一个模式,我会得到

'(()
  (())
  ((_0))
  (() ())
  ((_0 _1))
  (() (_0)
  ((_0) ())
  (() () ())
  ((_0 _1 _2)))

但我在雾中看不清楚,我希望能对此有所了解。这是我lolo的一个错误吗?它是 clojure.logic 中的错误吗?TRS 中的求解器和 clojure.logic 中的求解器之间存在合理的区别吗?我如何解释或使用结果?我如何在心理上预测 clojure.logic 的结果?

4

1 回答 1

7

正如您链接到的 core.logic wiki 页面所述,core.logicconde是 TRS 的condi. 不同之处在于 TRSconde按顺序尝试子句,而condi对结果流进行交错。所以 core.logic 版本将产生所有显示在 TRS 中的结果,但在它们之间,它会返回 miniKanren 永远无法处理的其他结果。

您的较长答案中的一个相关模式是,如果您从 开始获取第二个结果(()),则结果 seq 的子序列看起来就像整个结果 seq 并附()加到每个单独的结果。这是由于交错——在这个子序列上,()被选为结果的第一个元素,然后lolo递归地产生其余的元素。

于 2013-07-09T13:55:48.107 回答