Is there an idiomatic way to do hierarchical rules in clara? I have a set of rules that all calculate the same property from a fact but I would like the calculation only to be made by the most specific of the rules that match. I have tried inserting a guard fact when a rule (e.g. [:not [:guard (= (:active this) true] and (insert! {:type guard :active true}
) matches and using salience to control firing order, but this results in an endless loop for reasons I cannot figure out.
As an example I don't understand why the code below goes into an endless loop.
(defrule test-rule
"test guard"
[:not [:guard (= (:active this) true)]]
=>
(do
(println "Inserting guard!")
(insert! {:type :guard :active true})))
(-> (mk-session [test-rule]
:fact-type-fn :type)
(fire-rules))
@mac use a different guard type for each tier
Where the rule never inserts it’s own type
@mac https://gist.github.com/mrrodriguez/6a6f8373b25d69826b3efe154c928fac this actually has a somewhat similar model as well. For a slightly different goal but notice the guarding not conditions
@mikerod Thanks, the gist looks very useful. Do you know why my example would loop?
@mac the rules attempt to find a logical consistency balance
Your rule Left side condition is invalidated when the right side inserts.
The engine then retracts that’s fact because it is no longer logically supported.
It’s called the truth maintenance system
Then it can activate again and re insert. And again it invalidates itself. So it’s logical looping
@mikerod OK, so the guard gets removed because the LHS match that caused it to be inserted no longer matches?
Yes
Think of rules not like in order. But instead that the rhs facts inserted are supported by the lhs
@mikerod Got it, this is much closer to logic programming than I thought, but it makes sense when framed like that.