Fork me on GitHub
#clara
<
2018-05-20
>
dominicm08:05:37

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?

dominicm08:05:10

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

alex-dixon17:05:19

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

dominicm17:05:08

@alex-dixon sorry, I'm struggling to understand. Can you try in different terms.

alex-dixon17:05:43

What’s happening seems completely wrong

alex-dixon17:05:27

Your rule expresses a join your input data can satisfy at most once

alex-dixon17:05:17

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

alex-dixon17:05:22

Have you tried restarting the repl?

alex-dixon17:05:22

Something just seems wildly off. Do you think it could be caused by old repl state?

dominicm18:05:11

I'll try a restart of the repl. I had presumed a fresh namespace was enough.

alex-dixon18:05:16

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?

dominicm18:05:33

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.

alex-dixon18:05:07

I see in the source mk session with no args uses /ns/

alex-dixon18:05:02

With earmuffs

dominicm18:05:08

` is what you're after

alex-dixon18:05:36

Yeah...Apple doesn’t have that on their phones

dominicm18:05:36

oh 😞 silly fruit

alex-dixon18:05:41

The last result is the most glaring

alex-dixon18:05:02

Try binding the whole fact and printing that out. I may be confused

dominicm18:05:47

which fact, first, second or both?

alex-dixon18:05:04

?fact1 <- condition 1 ?fact2 <- condition 2

dominicm18:05:51

(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}

alex-dixon18:05:05

Ok so the fact types are right I was mistaken on that

dominicm18:05:16

I suppose that in [?b <- DatabaseBoxEngine (= ?dbox e) (= ?v v)] The (= ?dbox e) is being ignored.

thegeez22:05:27

(= (->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

thegeez23:05:03

@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

thegeez23:05:33

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