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?@oskarkv I think it’s invalid to do a “fact binding” on an :exists
Now that I see that syntax, makes me wonder why it works
So basically, I think more
is invalid - but I guess it isn’t being checked well
I don’t understand how it could have any semantically meaningful compilation result
:exists
in general does not allow you to access the fact that “exists”
because it isn’t meaningful directly - there could be more than one
if you need to have an actual fact - and I suppose any fact will do for you - you should use an accumulator
[?items <- (acc/all) :from [Item ...]]
=>
;; choose one here
... (first ?items) ...
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
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