在函数core.logic
,我看到以下clojure.core.logic/everyg
定义。
一个伪关系,它采用 coll 并确保目标 g 在集合的每个元素上都成功。
在这种情况下,pseudo-relation
究竟意味着什么?
以下是对关系(和非关系)的一个很好的解释:非关系在实践中对core.logic意味着什么?另一个背景是everyg
在此提交中从everyo
重命名,因为o
后缀应该仅用于关系。
关系目标的一个属性是,当所有/部分/没有输入是非地面的时,它们可以提供答案。conso
是关系的,因此我们可以问,在l
a
附加到d
,其中所有变量都是新鲜的,满足关系的值是什么:
(run* [a d l] (conso a d l))
=> ([_0 _1 (_0 . _1)])
这告诉我们a
(_0
)是新鲜的,d
(_1
)是新鲜的,l
((_0 . _1)
)a
在前面加上d
。虽然这些值都不是根据的,但我们仍然可以在答案中看到它们之间的关系。
对于everyg
来说,情况并非如此:
(run* [g coll] (everyg g coll)) ;; Don't know how to create ISeq from: clojure.core.logic.LVar
everyg
无法告诉我们g
和coll
之间的关系是什么,也无法告诉我们如果我们提供任何一种地面价值,g
或coll
可能是什么:
(run* [coll] (everyg succeed coll)) ;; throws
(let [coll (repeatedly 3 lvar)] ;; throws too
(run* [g]
(everyg g coll)))
虽然everyg
本身不是一个关系,但你可以向它传递一个目标g
,并coll
新的和/或地面变量:
(let [coll (cons 1 (repeatedly 2 lvar))] ;; 1 prepended to two fresh logic vars
(run* [q]
(== q coll)
(everyg #(fd/in % (fd/domain 0 1)) coll)))
=> ((1 0 0) (1 1 0) (1 0 1) (1 1 1))
无论everyg
目标的位置如何,此示例都将给出相同的答案,这是关系目标的另一个属性。
我们可以将conso
关系传递给具有所有新逻辑变量的everyg
,并且仍然可以在答案中看到该关系,就像上面conso
示例一样:
(run* [a d q]
(everyg #(conso a d %) [q]))
=> ([_0 _1 (_0 . _1)])
因此,有一些警告,everyg
可以在关系上使用,这就是为什么我认为它被认为是伪关系而不是非关系。