Fork me on GitHub
#clara
<
2020-05-13
>
oskarkv10:05:16

When using :exists, adding a binding variable changes the behaviour of the rule, making it trigger more times. For example (only difference being ?i <- in more):

(cr/defrule more
  [?p <- Player (= id ?id)]
  [:exists [?i <- Item (= id ?id)]]
  =>
  (println "more" ?p))

(cr/defrule less
  [?p <- Player (= id ?id)]
  [:exists [Item (= id ?id)]]
  =>
  (println "less" ?p))
prints:
more #claraz.rules.Player{:id 2, :y 2}
more #claraz.rules.Player{:id 1, :y 1}
more #claraz.rules.Player{:id 2, :y 2}
more #claraz.rules.Player{:id 1, :y 1}
more #claraz.rules.Player{:id 1, :y 1}
less #claraz.rules.Player{:id 2, :y 2}
less #claraz.rules.Player{:id 1, :y 1}
I find that a bit unintuitive. Is it supposed to be this way?

mikerod13:05:06

@oskarkv I think it’s invalid to do a “fact binding” on an :exists

mikerod13:05:16

Now that I see that syntax, makes me wonder why it works

mikerod13:05:00

So basically, I think more is invalid - but I guess it isn’t being checked well

mikerod13:05:15

I don’t understand how it could have any semantically meaningful compilation result

mikerod13:05:27

:exists in general does not allow you to access the fact that “exists”

mikerod13:05:41

because it isn’t meaningful directly - there could be more than one

mikerod13:05:09

if you need to have an actual fact - and I suppose any fact will do for you - you should use an accumulator

mikerod13:05:08

[?items <- (acc/all) :from [Item ...]]
=>
;; choose one here
... (first ?items) ...

mikerod13:05:27

In your case, you may be thinking that in your domain there is exactly 1 match or no matches. However, the rules do not know this

mikerod13:05:06

I do find the situation where the syntax is allowing this fact binding to be put inside the :exists condition to be something to be addressed though