使用core.logic来创建一个简单的匹配函数

时间:2016-04-16 02:15:25

标签: clojure clojurescript clojure-core.logic

假设我们通过下表定义了一个关系matches

|-----+-----+-----+-----+-----|
|     | *A* | *B* | *C* | *D* |
|-----+-----+-----+-----+-----|
| *A* |     | X   | X   |     |
|-----+-----+-----+-----+-----|
| *B* | X   |     |     | X   |
|-----+-----+-----+-----+-----|
| *C* | X   |     |     |     |
|-----+-----+-----+-----+-----|
| *D* |     | X   |     |     |
|-----+-----+-----+-----+-----|

这意味着(在pseduo代码中)

(matches A) ;=> (B C)
(matches B) ;=> (A D)
(matches C) ;=> (C)
(matches D) ;=> (B)

在core.logic中,我想我会知道如何制作可以近似matches行为的个性化函数:

(defn matches-A
  (run* [q]
    (membero q [B C]))) ;=> (B C)

......等matches-Bmatches-C

问题:如何将matches-A概括为如上所述的单个函数matches?特别是,我有兴趣制作它,以便您可以运行(matches "not A")(matches "B and C")(matches "C or D")(在伪代码中)等查询来获取(A D)之类的结果,(A)(A B)。这可能吗?

注意:我正在使用clojurescript而不是clojure。我不确定这是否会对答案产生影响。

1 个答案:

答案 0 :(得分:2)

您可以使用conde来解决此任务:

(ns qradv.welcome
  (:require [cljs.core.logic :as l]))

;; |-----+-----+-----+-----+-----|
;; |     | *A* | *B* | *C* | *D* |
;; |-----+-----+-----+-----+-----|
;; | *A* |     | X   | X   |     |
;; |-----+-----+-----+-----+-----|
;; | *B* | X   |     |     | X   |
;; |-----+-----+-----+-----+-----|
;; | *C* | X   |     |     |     |
;; |-----+-----+-----+-----+-----|
;; | *D* |     | X   |     |     |
;; |-----+-----+-----+-----+-----|
(defn matches [x]
  (l/run* [y]
    (l/conde
      [(l/== x "A") (l/membero y ["B" "C"])]
      [(l/== x "B") (l/membero y ["A" "D"])]
      [(l/== x "C") (l/membero y ["C"])]
      [(l/== x "D") (l/membero y ["B"])])))

(prn (matches "A"))
(prn (matches "B"))
(prn (matches "C"))
(prn (matches "D"))

输出:

("B" "C")
("A" "D")
("C")
("B")