I seem to have identified a big misunderstanding on my part:
(ns bugB
(:require
[clara.rules :refer :all]))
(defrecord DatabaseBox [id])
(defrecord AWSDBInstance [id])
(defrecord DatabaseBoxEngine [e v])
(defrecord AWSDBInstanceEngine [e v])
(defrecord RollCreatedFor [e v])
(defrule DatabaseBox-Engine
[RollCreatedFor (= e ?dbi) (= v ?dbox)]
[DatabaseBoxEngine (= e ?dbox) (= ?v v)]
=>
(println ?dbi ?dbox ?v))
(comment
(clear-ns-productions!)
(let [foo (->DatabaseBox "foo")
foo-db (->AWSDBInstance "foo")
foo-db-backup (->AWSDBInstance "foo-backup")]
(-> (mk-session)
(insert
foo
(->DatabaseBoxEngine foo :postgres)
foo-db
(->RollCreatedFor foo-db foo)
foo-db-backup
(->RollCreatedFor foo-db-backup foo-db)
(->RollCreatedFor foo-db-backup foo))
(fire-rules))))
I cannot understand why this prints #bugB.AWSDBInstance{:id foo-backup} #bugB.AWSDBInstance{:id foo} :postgres
(among the 2 other results, I expect of AWSDBInstace with a DatabaseBox). I particularly don't understand how it finds a DatabaseBoxEngine where e
is an AWSDBInstance?The total output:
#bugB.AWSDBInstance{:id foo} #bugB.DatabaseBox{:id foo} :postgres
#bugB.AWSDBInstance{:id foo-backup} #bugB.DatabaseBox{:id foo} :postgres
#bugB.AWSDBInstance{:id foo-backup} #bugB.AWSDBInstance{:id foo} :postgres
Looks like the only a database box engine has an e of foo record and if that’s your only rule there’s no way it should match on two different fact types when the fact type function is type
@alex-dixon sorry, I'm struggling to understand. Can you try in different terms.
What’s happening seems completely wrong
Your rule expresses a join your input data can satisfy at most once
And your rule specifies a join on two different fact types. So a match for it that contains only one fact type should be impossible
Have you tried restarting the repl?
Something just seems wildly off. Do you think it could be caused by old repl state?
I'll try a restart of the repl. I had presumed a fresh namespace was enough.
I would too. I’m not sure how records refresh or whether they are repl friendly in general (think they need imported?). I see you were using clear ns productions but it’s not clear to me how rules are being loaded using mk session without passing in the productions?
I'm still getting this behaviour:
#bugB.AWSDBInstance{:id foo} #bugB.DatabaseBox{:id foo} :postgres
#bugB.AWSDBInstance{:id foo-backup} #bugB.DatabaseBox{:id foo} :postgres
#bugB.AWSDBInstance{:id foo-backup} #bugB.AWSDBInstance{:id foo} :postgres
I experimented with (clear-ns-productions!)
, but I'm not actually running it anymore.I see in the source mk session with no args uses /ns/
yes 🙂
*ns*
With earmuffs
Thx lol
` is what you're after
Yeah...Apple doesn’t have that on their phones
oh 😞 silly fruit
The last result is the most glaring
Try binding the whole fact and printing that out. I may be confused
which fact, first, second or both?
?fact1 <- condition 1 ?fact2 <- condition 2
(defrule DatabaseBox-Engine
[?a <- RollCreatedFor (= e ?dbi) (= v ?dbox)]
[?b <- DatabaseBoxEngine (= ?dbox e) (= ?v v)]
=>
(prn ?a ?b))
=>
; #bugB.RollCreatedFor{:e #bugB.AWSDBInstance{:id "foo"}, :v #bugB.DatabaseBox{:id "foo"}} #bugB.DatabaseBoxEngine{:e #bugB.DatabaseBox{:id "foo"}, :v :postgres}
; #bugB.RollCreatedFor{:e #bugB.AWSDBInstance{:id "foo-backup"}, :v #bugB.DatabaseBox{:id "foo"}} #bugB.DatabaseBoxEngine{:e #bugB.DatabaseBox{:id "foo"}, :v :postgres}
; #bugB.RollCreatedFor{:e #bugB.AWSDBInstance{:id "foo-backup"}, :v #bugB.AWSDBInstance{:id "foo"}} #bugB.DatabaseBoxEngine{:e #bugB.DatabaseBox{:id "foo"}, :v :postgres}
Ok so the fact types are right I was mistaken on that
I suppose that in [?b <- DatabaseBoxEngine (= ?dbox e) (= ?v v)]
The (= ?dbox e)
is being ignored.
(= (->DatabaseBox "foo")
(->AWSDBInstance "foo")) ;; => false
(.equals (->DatabaseBox "foo")
(->AWSDBInstance "foo")) ;; => true
So there is probably some confusion in some of the java collections used within clara@dominicm the problem is here: https://github.com/cerner/clara-rules/blob/master/src/main/clojure/clara/rules/platform.cljc#L11 Replace the group-by-seq with
(seq (group-by f coll))
and it works properly again(platform/group-by-seq vector
[(->DatabaseBox "foo")
(->AWSDBInstance "foo")])
;; => [[[#clara_bug.core.DatabaseBox{:id "foo"}] [#clara_bug.core.DatabaseBox{:id "foo"} #clara_bug.core.AWSDBInstance{:id "foo"}]]]
(defn group-by-seq [f coll]
(seq (group-by f coll)))
(group-by-seq vector
[(->DatabaseBox "foo")
(->AWSDBInstance "foo")])
;; => ([[#clara_bug.core.DatabaseBox{:id "foo"}] [#clara_bug.core.DatabaseBox{:id "foo"}]] [[#clara_bug.core.AWSDBInstance{:id "foo"}] [#clara_bug.core.AWSDBInstance{:id "foo"}]])