Anyone using precept with Clojure here? I'm having trouble to find out how to work with Queries on precept's side (I can always use Clara-Rules' queries, but I think using precept helpers would be easier here).
Hey @mauricio.szabo. I’m working on improving Clojure support. The current design works well for the browser where 99 percent of the time it’s a single context, but the use of global state is problematic for other environments
I would expect queries with defquery to work as they do in Clara. If you’re looking to use subscriptions you may run into issues in CLJ. Apart from global state issues we don’t have a good implementation of a reagent cursor for Clojure. The subscription implementation depends on that a fair bit
I saw that there's a defquery
for precept too. Would it help?
Also, how can I use entities-where
?
Admittedly we haven’t used queries much and tend to use subscriptions in Clojurescript, so it’s possible the query api is lagging behind or not working in some way. If you have an example or want to open an issue feel free to share, will do the best I can to help
> I saw that there’s a defquery
for precept too. Would it help?
See above. It’s definitely worth trying yeah. It’s just like Clara except more datalog syntax and expects facts to be tuples
Okay, I'll try to use it. I'll try to post questions here as soon as I found myself blocked
> Also, how can I use entities-where
?
That should probably be depreciated but may work if you pass a precept session and an attribute or attribute and a value. That code was written early on and we discovered those queries were pretty unrestricted…so the rete graph works overtime to build nodes for every possible combination of e a v more or less. tldr; if it does work it might not be performant
Okay, I don't seem to make it work correctly... I've added a rule:
(def schema [(attribute :user/name :db.type/string)
(attribute :user/status :db.type/keyword)])
(rule new-user-is-active
[[?id :user/name ?name]]
=>
(util/insert! [?id :user/status :active])))
Then, created a session with (session students 'rules.experiments :db-schema schema :client-schema schema)
, but what should I do after this? I've tried to use start!
:
(precept.core/start! {:session students
:facts [[(precept.util/guid) :user/name "FooBar"]]})
But then, any query I try to use returns an empty list, and I don't know how could I create a Clara's query to use it... also, start!
seems to asynchronous fire rules, so I'm not sure on how to use it on a unit test. Is there an example in Clojure that I could follow?I might have one…let me see
I’d have to obfuscate it…can do just few questions to see if there’s a faster way for both of us 🙂 is new-user-is-active
firing? Easiest way is to have println before the insert
Yes, it is firing. The code I tested was:
(defquery all-users []
[?fact <- [_ :user/name _]]) ; and multiple variants of this, with ?id and ?name
(comment
(let [{:keys [session]}
(precept.core/start! {:session students
:facts [[(precept.util/guid) :user/name "FooBar"]]})]
(prn [:RULES (clara/query session all-users)])))
It printed [:RULES...
before my rule was firedHm ok. There may be a bug then. I can look at the source for defquery in a sec and see if there’s anything obviously wrong
An alternative would be to use defsub and then read the subscription from precept.state/store…
(rules/defsub :my-sub
[?fact <- [?user :user/name _]]
=>
{:data [?user ?fact]})
Then underneath start/above prn register the subscription with:
(precept/subscribe [:my-sub])
Then you could read it with something like
(defn read-subscription [name]
(let [id (some #(when (= name (:name %)) (:id %)) (vals (:subscriptions @precept.state/state)))]
(get-in @precept.state/store [id :precept.spec.sub/response])))
(read-subscription :my-sub)