Rule with just [:not A] => (insert A) seems broken
oskarkv opened this issue · comments
I have this code:
(defrecord Dice [dice])
(cr/defrule dice
[:not [Dice]]
=>
(cr/insert! (->Dice 1))
(println "inserted dice")
(Thread/sleep 100))
(defn test-clara []
(-> (cr/mk-session)
cr/fire-rules))
I expect this to fire the dice
rule once and nothing else. But it just keeps firing it. This is my output:
game.server.core> (test-clara)
inserted dice
inserted dice
inserted dice
inserted dice
inserted dice
inserted dice
inserted dice
inserted dice
If I interrupt that and check the rule it's:
game.server.core> dice
{:ns-name game.server.core,
:lhs [[:not {:type game.server.core.Dice, :constraints []}]],
:rhs
(do (cr/insert! (->Dice 1)) (println "inserted dice") (Thread/sleep 100)),
:name "game.server.core/dice"}
I'm having (Thread/sleep 100)
in there because otherwise the REPL becomes unresponsive when it is stuck in a loop.
Even weirder is that I had some problems with old rules still being defined (because of defrule
) so I restarted Clojure, multiple times. And sometimes the rule does work ("inserted dice" printed only once) and sometimes it doesn't. I felt like I was going mad.
Also, I tried with
(cr/defrule dice
[:not [Dice]]
[?dice <- (acc/count) :from [Dice]]
=>
(cr/insert! (->Dice 1))
(println "inserted dice")
(println "number of dice:" ?dice)
(Thread/sleep 100))
And it prints:
inserted dice
number of dice: 0
inserted dice
number of dice: 0
inserted dice
number of dice: 0
forever.
This is called truth maintenance. http://www.clara-rules.org/docs/truthmaint/
Your rule inserts a Dice fact, which causes ':not Dice' to no longer be true, so it retracts Dice, which causes ':not Dice' to be true, which inserts a Dice, and so on and so forth.
Oh, of course. Thanks @Zylox