我试图理解core.logic
如下定义的自定义约束,
(defne lefto
"x appears to the left of y in collection l."
[x y l]
([_ _ [x . tail]] (membero y tail))
([_ _ [_ . tail]] (lefto x y tail)))
如何解释_
和.
在上下文中core.logic
?
我试图理解core.logic
如下定义的自定义约束,
(defne lefto
"x appears to the left of y in collection l."
[x y l]
([_ _ [x . tail]] (membero y tail))
([_ _ [_ . tail]] (lefto x y tail)))
如何解释_
和.
在上下文中core.logic
?
defne
是一个使用特殊模式匹配语法的宏,但行为类似于conde
. (仅供参考e
,其中每一个都代表“一切”,即每个子句都可以贡献。)
_
值,但您不在乎它是什么。.
表示 左侧的项目.
和右侧的列表尾部的串联.
。这用于将列表的单个项目和列表的其余部分绑定到不同的值。(另见llist
core.logic。)Clojure 中类似的序列解构将使用&
代替.
:
(let [[_ _ [_ & tail]] coll] ...)
所以下面的模式意味着“我们不关心第一个或第二个输入参数,但第三个应该是我们头部所在的列表x
(即等于函数的x
输入参数)并将尾部绑定到tail
”:
[_ _ [x . tail]]
另请注意,tail
此处可以是空列表,并且可以在.
.
由于您的示例是一个递归目标,因此它最终将通过 find x
before终止y
,或者它将无法匹配任何一种模式,因为l
(最终)将是()
与任何一种情况都不匹配的空列表。
membero
定义本身是相同想法的一个更简单的示例:
(defne membero
"A relation where l is a collection, such that l contains x."
[x l]
([_ [x . tail]])
([_ [head . tail]]
(membero x tail)))
有两个子句,每个子句都由一个顶级列表表示()
:
[_ [x . tail]]
- 第一个表示我们不想匹配_
的输入参数。描述了第二个参数的模式,如果是 的头部,则该模式匹配并成功。x
[x . tail]
l
x
l
membero
[_ [head . tail]
- 这里的_
意思是一样的。但请注意,我们为 的头部 赋予了一个新名称l
,它只需要是一个非空列表即可满足此模式。如果匹配,那么我们递归(membero x tail)
继续搜索。x
通过在 ; 的(子)列表中查找,只有第一个子句可以使目标成功l
。第二个子句仅用于解构head
and tail
ofl
和recurse。
以下是使用和没有模式匹配的membero
翻译:conde
(defn memberoo [x l]
(conde
[(fresh [a d]
(conso a d l)
(== a x))]
[(fresh [a d]
(conso a d l)
(memberoo x d))]))