clara

sparkofreason 2021-10-26T17:14:09.002100Z

Given the definitions below:

(ns ck.repro
  (:require [clara.rules :as rules :refer [defsession defrule defquery]]))

(defrecord MakeStuff [stuff])
(defrecord Stuff [foo])

(defrule add-stuff
  [:not [:exists [Stuff]]]
  =>
  (println "Add stuff")
  (rules/insert! (->MakeStuff (->Stuff "foo"))))

(defrule make-stuff
  [?make-stuff <- MakeStuff (= ?stuff stuff)]
  =>
  (println "Make stuff")
  (rules/insert-unconditional! ?stuff))

(defquery make-stuff?
  []
  (?make-stuff <- MakeStuff))

(defrule exists-stuff
  [:exists [Stuff]]
  =>
  (println "Found stuff"))

(def session (-> (rules/mk-session 'ck.repro)
                 (rules/fire-rules)))

(println "make-stuff?" (rules/query session make-stuff?))
I get the following output:
Add stuff
Make stuff
Found stuff
make-stuff? ({:?make-stuff #ck.repro.MakeStuff{:stuff #ck.repro.Stuff{:foo foo}}})
I would have expected that the make-stuff rule would cause the MakeStuff fact inserted by add-stuff to be retracted by truth maintenance. Am I missing something?

Mario C. 2021-10-26T22:47:31.003300Z

The make-stuff rule is using insert-unconditional! which will prevent the fact inserted from being retracted. Otherwise you would have an infinite loop with the above stated rules

ethanc 2021-10-26T23:25:55.005400Z

bizarre…. At first blush i would say that something about the “Exists” accumulator is acting suspiciously in the retraction path. For example, written differently:

(r/defrule add-stuff
  [:not [Stuff]]
  =>
  (println "Add stuff")
  (r/insert! (->MakeStuff (->Stuff "foo"))))
Add stuff
Make stuff
Found stuff
make-stuff? ()

ethanc 2021-10-26T23:27:07.006200Z

additional sanity:

(r/defquery stuff?
  []
  (?stuff <- Stuff))
nets the expected:
Add stuff
Make stuff
Found stuff
make-stuff? ()
stuff? ({:?stuff #Stuff{:foo foo}})

ethanc 2021-10-26T23:49:30.006700Z

@dave.dixon what version of clara are you running?

sparkofreason 2021-10-26T23:57:16.006800Z

0.21.1

👍 1