2016-04-16 6 views
1

Angenommen, wir definieren eine Beziehung matches über die folgende Tabelle machen:Mit core.logic eine einfache Anpassungsfunktion

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

Damit ist gemeint, dass (in pseduo-Code)

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

In core.logic, ich glaube, ich weiß, wie individualisierte Funktionen zu machen, die das Verhalten von matches annähern könnte:

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

... und so weiter für matches-B und matches-C.

Frage: Wie könnte ich verallgemeinern, d. H. matches-A zu einer einzigen Funktion wie oben? Insbesondere wäre ich daran interessiert, es so zu machen, dass Sie Abfragen wie (matches "not A"), (matches "B and C") und (matches "C or D") (in Pseudocode) ausführen können, um Ergebnisse wie (A D), (A) bzw. (A B) zu erhalten. Ist das möglich?

HINWEIS: Ich verwende Clojurescript anstelle von Clojure. Ich bin mir nicht sicher, ob das die Antwort überhaupt beeinflussen würde.

Antwort

2

können Sie conde verwenden, diese Aufgabe zu lösen:

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

Ausgang:

("B" "C") 
("A" "D") 
("C") 
("B") 
+0

Gibt es eine Möglichkeit logische Argumente in dieser Funktion einbetten (wie "A und B" oder „nicht C " und so weiter)? – George

+0

@George Ich bin mir nicht sicher, wie Sie 'nicht C' verwenden möchten. Können Sie ein Beispiel hinzufügen, um die Tabelle zu beschreiben? – edbond

+0

Guter Punkt - das hat mehrdeutige Bedeutung. Mit - d.h. - "nicht C" meine ich "(B C D)". Das heißt, ich meine das Komplement dessen, was mit C übereinstimmt (im Gegensatz zu der Summe dessen, was mit dem Komplement von C übereinstimmt). – George