clara-rules
clara-rules copied to clipboard
Issue 238: Throw exception when a rule has duplicate result bindings
It does seem that the engine doesn't crash in this circumstance. The question is whether it is useful behaviour. Some samples I tried:
(defrule sample-should-fail-rule
[?binding <- Cold]
[?binding <- Hot]
=>
(insert! (->LousyWeather)))
(defrule sample-run-rule
[?binding <- Cold]
[?binding <- Cold]
=>
(insert! (->LousyWeather)))
(defrule should-not-match-rule
[?binding <- Cold]
[?binding <- Cold (not (identical? this ?binding))]
=>
(insert! (->LousyWeather)))
(-> (mk-session [sample-run-rule lousy-weather-query]) clara.tools.tracing/with-tracing (insert (->Cold :cold)) fire-rules (query lousy-weather-query))
({:?weather #clara.rules.testfacts.LousyWeather{}})
(-> (mk-session [sample-should-fail-rule lousy-weather-query]) clara.tools.tracing/with-tracing (insert (->Cold :cold) (->Hot :hot)) fire-rules (query lousy-weather-query))
()
(-> (mk-session [should-not-match-rule lousy-weather-query]) clara.tools.tracing/with-tracing (insert (->Cold :cold) (->Hot :hot)) fire-rules (query lousy-weather-query))
()
I've always thought of rules as being the Cartesian join of different sets, which would make statements like this either nonsensical or always false (and thus not useful). That said, so far the examples I've tried seem to be always false i.e. the rule doesn't fire, although I'm fairly confident this wasn't by design. I suspect it might still be possible to break that behaviour but haven't yet found an example.
If we did want to support the behaviour of having rules like this always not match but run we should probably explicitly test that. I'm still not sure it is useful behaviour though. I'm having trouble thinking of sensible examples where it wouldn't be better to just add the constraints to one condition. The only thing I can think of so far is if you are validating that a fact is one of multiple different types, e.g.
(defrule multiple-type-rule
[?temp <- Cold]
[?temp <- VeryCold]
=>
....)
where you expect one fact object to satisfy both types.
If we did make it an optional linter I'd be tempted to have it turned on by default for things like this. Maybe stuff like this could happen when using Clara as a compilation target, it just seems very weird for a human to write.
Probably a weird scenario but what is the behavior of:
(defrule some-rule
[:or [?b <- SomeFact] [?b <- SomeOtherFact]]
=>
(<do something sketchy with ?b>))
Im not even sure what the behavior is today, but i will try and post back
Closing as commented on https://github.com/cerner/clara-rules/issues/238