Fork me on GitHub
#precept
<
2018-08-14
>
mauricio.szabo15:08:54

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).

alex-dixon15:08:39

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

alex-dixon15:08:46

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

mauricio.szabo15:08:19

I saw that there's a defquery for precept too. Would it help? Also, how can I use entities-where?

alex-dixon15:08:40

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

alex-dixon15:08:08

> 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

mauricio.szabo15:08:07

Okay, I'll try to use it. I'll try to post questions here as soon as I found myself blocked

👍 4
alex-dixon15:08:44

> 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

mauricio.szabo18:08:43

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?

alex-dixon18:08:59

I might have one…let me see

alex-dixon18:08:19

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

mauricio.szabo18:08:16

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 fired

alex-dixon18:08:08

Hm 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

alex-dixon18:08:29

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]})


alex-dixon18:08:55

Then underneath start/above prn register the subscription with:

(precept/subscribe [:my-sub])

alex-dixon18:08:39

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)