3

我试图理解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

4

1 回答 1

4

defne是一个使用特殊模式匹配语法的宏,但行为类似于conde. (仅供参考e,其中每一个都代表“一切”,即每个子句都可以贡献。)

  • 下划线表示必须存在的_值,但您不在乎它是什么。
  • .表示 左侧的项目.和右侧的列表尾部的串联.。这用于将列表的单个项目和列表的其余部分绑定到不同的值。(另见llistcore.logic。)

Clojure 中类似的序列解构将使用&代替.

(let [[_ _ [_ & tail]] coll] ...)

所以下面的模式意味着“我们不关心第一个或第二个输入参数,但第三个应该是我们头部所在的列表x(即等于函数的x输入参数)并将尾部绑定到tail”:

[_ _ [x . tail]]

另请注意,tail此处可以是空列表,并且可以在..

由于您的示例是一个递归目标,因此它最终将通过 find xbefore终止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)))

有两个子句,每个子句都由一个顶级列表表示()

  1. [_ [x . tail]]- 第一个表示我们不想匹配_的输入参数。描述了第二个参数的模式,如果是 的头部,则该模式匹配并成功。x[x . tail]lxlmembero
  2. [_ [head . tail]- 这里的_意思是一样的。但请注意,我们为 的头部 赋予了一个新名称l,它只需要是一个非空列表即可满足此模式。如果匹配,那么我们递归(membero x tail)继续搜索。

x通过在 ; 的(子)列表中查找,只有第一个子句可以使目标成功l。第二个子句仅用于解构headand tailofl和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))]))
于 2019-07-07T15:37:03.383 回答