core.logic 解释“新鲜”如何改变结果
core.logic explain how `fresh` changes results
刚开始使用 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)`
有人能解释一下这里发生了什么吗?
core.logic 可以看作是一种搜索算法,搜索可能的方法来为所有相关变量赋值,而不会导致冲突。它有很多非常聪明的剪枝技术,所以它不会搜索已知不好的子树,但基本上它是一个搜索。
它找到了两种分配满足您查询的变量的方法:
- a=2,q=1
- a=3,q=1
所以它返回了两个结果。但是你只询问 q(这就是 run*
的参数,你想知道其值的变量集),并且 q 在这两个赋值中是相同的,所以你看到相同的结果( 1)两次。一般来说,您不应该假设 run*
的结果是不同的,除非您已付出一些努力使它们如此。
与上一个示例类似,您可以将三个值分配给 q,每个值都适用于您可以分配给 a 的三个值中的任何一个,因此您会得到 3*3=9 个结果,每个q值重复三次。这些结果的返回顺序(从您的角度来看)是任意的;实际上,它们的排序方式有助于 core.logic 防止在其他更复杂的程序中陷入僵局。如果你愿意,你可以看到所有的 a,q 对,写成 (q/run* [a q] ...)
.
刚开始使用 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)`
有人能解释一下这里发生了什么吗?
core.logic 可以看作是一种搜索算法,搜索可能的方法来为所有相关变量赋值,而不会导致冲突。它有很多非常聪明的剪枝技术,所以它不会搜索已知不好的子树,但基本上它是一个搜索。
它找到了两种分配满足您查询的变量的方法:
- a=2,q=1
- a=3,q=1
所以它返回了两个结果。但是你只询问 q(这就是 run*
的参数,你想知道其值的变量集),并且 q 在这两个赋值中是相同的,所以你看到相同的结果( 1)两次。一般来说,您不应该假设 run*
的结果是不同的,除非您已付出一些努力使它们如此。
与上一个示例类似,您可以将三个值分配给 q,每个值都适用于您可以分配给 a 的三个值中的任何一个,因此您会得到 3*3=9 个结果,每个q值重复三次。这些结果的返回顺序(从您的角度来看)是任意的;实际上,它们的排序方式有助于 core.logic 防止在其他更复杂的程序中陷入僵局。如果你愿意,你可以看到所有的 a,q 对,写成 (q/run* [a q] ...)
.