Hi, I ran into some unexpected behavior today. I managed to replicate it in a small example (not sure if it's minimal):
(defrecord A [n])
(defrecord B [m])
(defrecord C [m n])
(defrule loop-rule
[B (= ?m m)]
[C (= ?m m) (= ?n n)]
[:not [A (= ?n n)]]
=>
(println (str "A: " ?n))
(insert! (->A ?n)))
(-> (mk-session :cache false)
(insert (->B 1))
(insert (->C 1 2))
(insert (->C 1 3))
(fire-rules))
This results in an infinite loop. So I guess the rule is triggering on each insertion of a new A, always finding the other C to make things fire? I expected the A to be inserted just twice. Note that in my real life use case, the A type is also coming from another source, so that's why I'm checking it. Am I simply not understanding the :not?I think http://www.clara-rules.org/docs/truthmaint/ might be a good start.
The rule itself is contradicting itself
Ah, yes, now I get it
or perhaps it could be thought of as a self fulfilling prophecy
thanks for the fast reply!
and thanks for clara: I'm building a pretty product and it's been a joy to work with π
*pretty complex product
The minimal example of the looping behavior would probably be something like:
(defrecord A [n])
(clara/defrule not-a
[:not [A]]
=>
(clara/insert! (->A 12)))
Typically to prevent this loop i would use something like a βreasonβ field on the fact if possible to denote default from other facts.
Something like:
(defrecord A [n reason])
(r/defrule not-a
[:not [A (not= ::default reason)]]
=>
(r/insert! (->A 12 ::default)))