clara

http://www.clara-rules.org/
oskarkv 2020-05-13T10:50:16.098400Z

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?

2020-05-13T13:19:06.098900Z

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

2020-05-13T13:19:16.099200Z

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

2020-05-13T13:25:00.099500Z

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

2020-05-13T13:25:15.099900Z

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

2020-05-13T13:25:27.100200Z

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

2020-05-13T13:25:41.100600Z

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

2020-05-13T13:26:09.101200Z

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

2020-05-13T13:27:08.102300Z

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

2020-05-13T13:28:27.103Z

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

2020-05-13T13:29:06.103600Z

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

👍 1