Ok, after scrolling back … seems this is a common trap that newbies fall into with truth maintenance. Walking through an example of something like this would make a great example in the getting started documentation!
I am trying to build an object generator using the rules, here is a example:
(defrecord Widget [name material length parts])
(defrule add-widget
[:not [Widget]]
=>
(println "adding widget")
(rules/insert-unconditional! (->Widget "w1" "unknown" nil [])))
(defn pick-material []
(first (shuffle ["steel" "silver" "gold"])))
(defn pick-length [mat]
(condp = mat
"steel" (+ 10 (rand-int 20))
"silver" (+ 5 (rand-int 10))
"gold" (rand-int 10)))
(defrule set-widget-attrs
[?widget <- Widget (= ?name name) (= ?material material) (= ?length length) (= ?parts parts)]
[:test (and (nil? ?length) (= ?material "unknown"))]
=>
(println "setting material")
(let [new-mat (pick-material)
len (pick-length new-mat)]
(rules/insert-unconditional! (->Widget ?name new-mat len ?parts)))
(rules/retract! ?widget))
this runs but produces 2 widgets (fires twice) and I am not sure why.
I am trying to effectively update the widget attributes by creating a new one and retracting the old one. This is the output:
(def session (-> (rules/mk-session 'user)
(rules/fire-rules)))
adding widget
setting material
adding widget
setting material
(rules/query session widget?)
=>List(2)(
0: Map{:?widget: #user.Widget Map{:name: "w1", :material: "gold", :length: 4, :parts: Vector(0)}},
1: Map{:?widget: #user.Widget Map{:name: "w1", :material: "gold", :length: 0, :parts: Vector(0)}}
)If I remove the retract it only runs once, but leaves the fact with unknown material around … I guess my question is what is the usual way to do this sort of thing? do I just leave these intermediate facts around , or can I clean them up some how?
without the retract!:
List(2)(
0: Map{:?widget: #user.Widget Map{:name: "w1", :material: "gold", :length: 4, :parts: Vector(0)}},
1: Map{:?widget: #user.Widget Map{:name: "w1", :material: "unknown", :length: nil, :parts: Vector(0)}})Hi, I’m very new to clara and trying to use it to build an hierarchical data structure. I am having some trouble grasping the basics obviously. I have this following simple rule that I want to create one widget:
(defrecord Widget [material type num-gadgets])
(defn pick-type [type]
"intermediate")
(defn get-num-gadgets []
1)
(defrule add-widget
[?c <- (accum/count) :from (Widget (= material "steel"))]
[:test (= 0 ?c)]
=>
(println "adding widget")
(rules/insert! (->Widget "steel" (pick-type "foo") (get-num-gadgets))))
I expect that the test should resolve to false once it has created one widget, however this seems to loop forever. What am I doing wrong here?
I am also not sure if this ‘right’ way to create facts in the session?