刚开始使用core.logic,版本" 0.8.11":
(q/run* [q]
(q/fresh [a]
(q/membero a [2 3]))
(q/membero q [1]))
我不理解结果:(1 1)
。
我的理解是我使用fresh创建另一个变量a
,它可以取值2或3。
并且q
的值可以为1.因此,我希望看到类似:(1)
或(1 2 1 3)
,或([1 2] [1 3])
甚至({:q 1 :a 2} {:q 1 :a 3})
的内容,但不是实际结果。
另一个例子:
(q/run* [q]
(q/fresh [a]
(q/membero a [1 2 3])
(q/membero q [3 4 5])
(q/== a q)))
;; make sense to me, returns (3)
(q/run* [q]
(q/fresh [a]
(q/membero a [1 2 3]))
(q/membero q [3 4 5]))
;; does not make sense to me, returns (3 4 3 5 4 3 5 4 5)
;; I was expecting `(3 4 5)`
有人能解释一下这里发生了什么吗?
答案 0 :(得分:4)
core.logic可以被视为搜索算法,搜索可能的方法来为不会引起冲突的所有相关变量赋值。它有很多非常聪明的修剪技术,因此它不会搜索已知不好的子树,但基本上它是一个搜索。
它找到了两种方法来分配满足查询的变量:
所以它返回了两个结果。但是你只询问q(run*
的参数是什么,你想要知道的变量集是什么),并且q在这两个赋值中是相同的,所以你看相同的结果(1)两次。你不应该一般认为run*
的结果是不同的,除非你已经付出了一些努力来制作它们。
同样在上一个示例中,有三个值可以分配给q,并且每个值都适用于您可以分配给a的三个值中的任何一个,因此每个q值得到3 * 3 = 9个结果重复三次。返回这些结果的顺序(从您的角度来看)是任意的;实际上,它们的排序方式有助于core.logic防止在其他更复杂的程序中陷入僵局。如果您愿意,可以通过编写(q/run* [a q] ...)
来查看所有a,q对。