(Please let me know if this is not clear enough — I can add more detail and some example code if necessary.) If I have a rule LHS that somehow finds a fact by running some Clojure code (outside of Clara fact matching), is it possible to add that found fact as a dependency for any facts that the RHS inserts? At the moment I am getting the LHS to search all facts of the relevant type and match on an ID, but that’s inefficient.
Thanks for your reply and suggestion.
The end-goal is that Clara’s truth maintenance removes the derived fact if the supporting thing-2 is retracted.
I’ve tried your suggestion in my real code, but it actually makes things slower. I think I need to check the HashJoin documentation carefully to understand the subtleties.
FWIW, I’m dealing with a few thousand thing-2s and a few tens of thing-1s.
And actually, a colleague has found a different approach that means I probably won’t pursue this. 🙂 (Something around having facts that wrap the data that contains the thing-1s and thing-2s.)
Thanks again!
Glad you found an alternative The doc on HashJoin: http://www.clara-rules.org/docs/hash_joins/ As a follow-up to the initial question, i do not believe there would be any mechanisms to inform clara that there existed additional facts that support the execution of a rule. So again, glad you found an alternative.
Thank you, once more. I appreciate your help.
A little more information would probably be required for a proper answer, but my gut says that LHS bindings “should” possibly handle that.
Thanks. I’ll try to get an example together — perhaps at the weekend.
Here’s an example:
(ns clara-example
(:require
[clara.rules :as c]))
(c/defrule create-derived-thing
[:thing-1 [{thing-1-key :key
:as thing-1}]
(= ?thing-1-key thing-1-key)
(= ?thing-2
(find-thing-2 thing-1))]
[:test (some? ?thing-2)]
[:thing-2 [{thing-2-key :key}]
(= thing-2-key (:key ?thing-2))]
=>
(c/insert! {:type :derived-thing
:thing-1-key ?thing-1-key
:thing-2-key (:key ?thing-2)}))
The rule finds a fact of type :thing-1. It then calls find-thing-2, which returns a fact of type :thing-2.
I want to insert a derived fact that depends on both the fact of type :thing-1 and the fact of type :thing-2. I’m telling Clara about the second dependency by looking at all facts of type :thing-2 and matching on the key.
This is not very efficient!
Thank you, that's not at all what I was envisioning.
Would the end goal be that thing-2 is visible via session inspection(http://www.clara-rules.org/docs/inspection/)?
As a side note, i'd be interested in the performance characteristics of that join. Potentially re-writing it as something that would force a hashJoin node might help. ie.
(ns clara-example
(:require
[clara.rules :as c]))
(c/defrule create-derived-thing
[:thing-1 [{thing-1-key :key
:as thing-1}]
(= ?thing-1-key thing-1-key)
(= ?thing-2-key
(:key (find-thing-2 thing-1)))]
[:test (some? ?thing-2-key)]
[:thing-2 [{thing-2-key :key}]
(= thing-2-key ?thing-2-key)]
=>
(c/insert! {:type :derived-thing
:thing-1-key ?thing-1-key
:thing-2-key ?thing-2-key}))
Then again, even the added performance of a HashJoin node might not be enough if you were dealing with extremely large numbers of thing-1 and thing-2.