Fork me on GitHub
#clara
<
2018-03-03
>
Oliver George06:03:26

Newbie question... I'm struggling to write a rule which boils down to "This or that".

Oliver George06:03:32

(defrecord This [x])
  (defrecord That [y])
  (defrule this-or-that
    "Print This if fact exists, else print That."
    [:or [?x <- This] [?x <- That]]
    =>
    (println :this-or-that ?x))

  (-> (mk-session 'labs-costs-clara.core)
      (insert
        (->This 1)
        (->That 2))
      (fire-rules))

Oliver George06:03:47

This will print twice which isn't what I'm after.

Oliver George06:03:10

(my real example is patching data... if X exists use it else use some other facts to fill in the gap)

zylox06:03:25

ya, or isnt a xor, it can indeed follow both paths

zylox06:03:48

i tend to think of it as if you had two disjunct rules

zylox06:03:57

because that is pretty close to what it does

zylox06:03:34

if you want one but not the other...well you are going to want to use two rules with :not on This in one and That on the other

Oliver George06:03:47

That makes sense. My rules got a bit verbose which is what got me wondering.

Oliver George06:03:15

The only alternative I could imagine was some kind of maybe accumulator

Oliver George06:03:24

(e.g. distinct but expecting one fact)

zylox06:03:00

are you expecting only one, or potentially many

Oliver George06:03:42

My code was really "if summary value exists use it, else calculate from many other facts" but that's not critical to the general question.

Oliver George06:03:46

Thanks for your thoughts @zylox that makes me feel more confident

zylox06:03:09

gotcha. id suggest something like

(defrule with-summary
  ""
  [Summary (= ?data data)]
  =>
  (println ?data))

(defrule without-summary
  ""
  [:not [Summary]]
  [?others <- (acc/all) :from [SecondaryFacts]]
  
  =>
  (println ?others))
then

zylox06:03:15

best of luck

zylox06:03:40

without all the horrible syntax errors i just edited out haha