1
votes

Suppose we define a relation matches via the following table:

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

By this, it is meant that (in pseduo-code)

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

In core.logic, I think I would know how to make individualized functions which could approximate the behavior of matches:

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

...and so forth for matches-B and matches-C.

Question: How could I generalize, i.e., matches-A to a single function matches as above? In particular, I'd be interested in making it so that you could run queries like (matches "not A"), (matches "B and C") and (matches "C or D") (in pseudo-code) to get results like (A D), (A), and (A B) respectively. Is this possible?

NOTE: I'm using clojurescript instead of clojure. I'm not sure if that would impact the answer at all.

1

1 Answers

2
votes

You can use conde to solve this task:

(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"))

Output:

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