Fork me on GitHub

@surreal.analysis I think this is expected behavior. The contract from Clara is that the state after all rules finish firing will be consistent with the rules, but the steps Clara takes to get there inside fire-rules are undefined except if you provide salience. Your print statements are reflecting intermediate state in the rules engine that is eliminated before fire-rules returns. So in your first example, collect-invalids fired with no Invalid facts because none had been created yet; once Invalid facts were created it fired with them. If collect-invalids had inserted other fact(s) the facts inserted by the firing with no Invalid facts yet would be removed before fire-rules returned to the caller. For something like this I’d suggest using queries or inserting another fact using insert! since these will be adjusted by the truth maintenance system when Invalid facts are added to the session.


So something like (defquery invalid-query “query for Invalid” [Invalid (= reason ?reason)])


Or (defrecord CollectedInvalid [all-invalid-reasons])


(defrule get-all-invalid [?invalids <- (acc/all) :from [Invalid]] => ;; for exame


(defrule get-all-invalid [?invalids <- (acc/all) :from [Invalid]] =>


=> ;; do something here that doesn’t depend on intermediate state


Ignore "(defrule get-all-invalid [?invalids <- (acc/all) :from [Invalid]] => ;; for exame [9:33] ``” please, I was trying to set up a code block but apparently don’t know how to do so in Slack 😛


When you did


(defrule collect-invalids [?reasons <- (acc/all) :from [Invalid (= ?reason reason)]] => (prn "Invalid for: " (map :reason ?reasons)))


You don’t fire when there are no Invalid facts since ?reason is not bound elsewhere (this is the behavior as of 0.12.0 at least, we fixed some bugs around accumulators that release). However, the effect of adding the ?reason binding in the accumulator condition is that you collect all Invalid facts for each reason and fire once per distinct reason.


So something like (defrule get-windspeeds-at-location [?wind <- (acc/all) :from [WindSpeed (= ?location location)]] => ;; do something )


given four windspeeds, where two come from LocationA and two come from LocationB, would fire twice, once with ?wind bound to the WindSpeed from LocationA and once with ?wind bound to the WindSpeed facts from LocationB


Hopefully this clears things up, please ask if it doesn’t and if anyone has thoughts on things at that could be cleared up to reduce confusion I’d be interested