clara-rules icon indicating copy to clipboard operation
clara-rules copied to clipboard

Issue 238: Throw exception when a rule has duplicate result bindings

Open WilliamParker opened this issue 3 years ago • 2 comments

WilliamParker avatar Mar 01 '21 09:03 WilliamParker

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.

WilliamParker avatar Mar 02 '21 07:03 WilliamParker

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

EthanEChristian avatar Mar 11 '21 21:03 EthanEChristian

Closing as commented on https://github.com/cerner/clara-rules/issues/238

WilliamParker avatar Jun 11 '23 15:06 WilliamParker