I learned from the video of the lecture that clara-rules can be used for join operations between different entities, so I implemented a simple example myself.
(ns clara-rules.join
(:require [clara.rules :refer [defrule fire-rules insert insert! mk-session]]))
(defrecord TypeA [attr-a join-key])
(defrecord TypeB [attr-b join-key])
(defrecord TypeC [attr-a attr-b join-key])
(defrule Join
[TypeA (= ?jk-a join-key) (= ?a attr-a)]
[TypeB (= join-key ?jk-a) (= ?b attr-b)]
=>
(insert! (->TypeC ?a ?b ?jk-a)))
(defrule Print
[?result <- TypeC];; Will always match
=>
(println ?result))
(-> (mk-session)
(insert (->TypeA "a1" :foo)
(->TypeA "a2" :bar)
(->TypeA "a3" :baz)
(->TypeB "b1" :foo)
(->TypeB "b2" :bar)
(->TypeB "b3" :baz)
(->TypeB "b4" :qux))
(fire-rules))
;;#clara_rules.join.TypeC{:attr-a a1, :attr-b b1, :join-key :foo}
;;#clara_rules.join.TypeC{:attr-a a2, :attr-b b2, :join-key :bar}
;;#clara_rules.join.TypeC{:attr-a a3, :attr-b b3, :join-key :baz}
--Type C is printed for Type A and Type B pairs that have a common : join-key
as intended. You did it!
--(-> TypeB" b4 ": qux)
does not appear in the results because there is no TypeA fact with the same : join-key: qux
. I see.
<-
on the left side of defrule
Bind the fact itself to a variable, not the attribute of the fact.
Taking [? result <-TypeC]
as an example, the entire matched TypeC instance is bound to? result.
Recommended Posts