Case A
[:test (my-pred?)]
[MyFact [a] (= a ?a)]
=>
....
Case B
[MyFact [a] (= a ?a)]
[:test (my-pred?)]
=>
....
With A
, clara will call my-pred?
at mk-session
With B
, clara will call my-pred?
at fire-rules
There is docs about this behavior?I'm not sure there is any document referencing that behavior. It would be an odd scenario to have a test node that is independent of the other nodes in a production. A typical scenario would make that test node dependent on some upstream fact, thus making the test node evaluate some time during fire-rules
@ethanc can I disable it?
I'm not sure what you mean by disable it
. From your example above i am assuming that my-pred?
is some sort of stateful check, and if that is true then i would recommend against imbedding that sort of logic in the network itself, maybe moving it to the RHS of the rule.
It's not statefull. it access a *dynamic*
env var π
The use of a dynamic var would likely be considered stateful, as the state of the var would impact the result from the predicate.
Clara makes some pretty big assumptions on statelessness, as in it will not reevaluate conditions that it "doesn't have to". Air quoting doesn't have to
because clara determines what must be reevaluated by direct or indirect actions(Truth Maintenance) on the session, ie insertion or retraction of facts.
That being said, if there is statefulness in a session's rules and for some reason that state changes then all bets are off when it comes to the validity of the outcome of said rules.
Perhaps you could instead insert facts that represent the same thing that this dynamic var encapsulates
however, evaluating anything at βcompile timeβ of mk-session
seems weird to me. Iβd have to see it reproduced probably to understand what may be happening there
https://gist.github.com/souenzzo/e38e600d486532308084c2bba0a9b3e9 @mikerod
#tools-deps is awesme to report bugs β€οΈ
@souenzzo, I was looking at your example, it seems that the side effect that you mention is due to: https://github.com/cerner/clara-rules/blob/master/src/main/clojure/clara/rules/engine.cljc#L2050 which is used during the creation of the session as you described: https://github.com/cerner/clara-rules/blob/master/src/main/clojure/clara/rules.cljc#L264 The left activate in that snippet seems to be aimed at rules that have no LHS, ex:
(r/defrule insert-sentinel
=>
(r/insert! (->SomeFact)))
the token being passed is empty. This "bootstrapping" operation is likely done because these productions wouldn't have an alpha-root for them to be triggered later.
In your scenario:
(defrule rule1
[:test (my-pred? :rule1)]
[Fact (= a ?a)]
=>
(prn ["rule1" ?a]))
the first node in the beta-roots would be the test-node, as mentioned before this is not a normal pattern as test nodes are usually dependent on prior facts.
When the conditions are reversed the test node would not be evaluated as it would be a child node of a join node.PROPOSAL: If is possible to reach LHS, then run the RHS. If there is no how to reach LHS, then do not run anything in RHS. Is it possible? Is it reasonable? Should I open a issue? I think that I can try a PR.
@souenzzo I'm not sure i fully understand the intent of your proposal. The determination of RHS evaluation is done currently by percolating facts down the nodes until they ideally enter a ProductionNode, assuming all conditions are met. To do this we would still have to evaluate the truthiness of the LHS.