precept

Preception!
kenny 2017-06-09T00:00:02.681090Z

Ah, yes

alex-dixon 2017-06-09T00:00:14.683606Z

Looks like we might want to support that...

alex-dixon 2017-06-09T00:00:37.687577Z

You'd like to have for insertions correct?

kenny 2017-06-09T00:01:10.692982Z

That's how I was using it. Not sure if it's applicable elsewhere.

kenny 2017-06-09T00:04:53.727651Z

Have you guys gotten this to work in a "reloadable" fashion? Right now I need to refresh my whole page before the rules are redefined.

kenny 2017-06-09T00:05:16.731466Z

Sorry for the bombardment of questions šŸ˜ I really think you guys have hit the nail on the head here for UI development.

mikegai 2017-06-09T00:05:33.734013Z

@kenny we are loving it, keep it coming šŸ™‚

alex-dixon 2017-06-09T00:05:39.734879Z

You have no idea how helpful it is for us šŸ™‚

mikegai 2017-06-09T00:06:03.738529Z

BTW, I have added a note in issue #28 to make sure we support nested maps (per Kenny's example)

alex-dixon 2017-06-09T00:06:32.742808Z

Youā€™re not alone with having to refresh the page. I believe this is the case with Clara and think it has to do with their CLJS implementation

alex-dixon 2017-06-09T00:07:15.749049Z

Iā€™m really not sure though. It seems like the reloading should work even though weā€™re dealing with macros

kenny 2017-06-09T00:10:48.779456Z

Yeah, it certainly seems like it should just work given it's just interning a var.

kenny 2017-06-09T00:13:48.803695Z

I'll open an issue so it can be kept in mind. Certainly worth investigating.

alex-dixon 2017-06-09T00:14:02.805636Z

Oh thanks I was just about to šŸ™‚

alex-dixon 2017-06-09T00:14:05.806108Z

Good issue

kenny 2017-06-09T00:18:07.839190Z

https://github.com/CoNarrative/precept/issues/80.

kenny 2017-06-09T00:18:44.844256Z

Is there anyway to see a list of all facts currently in the session? I see Clara has clara.tools.inspect but that isn't available in CLJS.

alex-dixon 2017-06-09T00:20:33.859175Z

Thanks for opening that

alex-dixon 2017-06-09T00:22:21.874320Z

Well, one way is to write a print all facts rule.

(rule print-all-facts
  [?fact <- [_ :all]]
  =>
 (println "Fact!" ?fact)

alex-dixon 2017-06-09T00:24:12.889009Z

You can see the viewmodel/store state by derefing precept.state/store. They wonā€™t be in tuple format and but they should be what you have in the session at the end of every fire-rules

alex-dixon 2017-06-09T00:24:33.891816Z

Itā€™s also what your components ultimately get

kenny 2017-06-09T00:28:11.921200Z

Ah yeah, that is useful.

alex-dixon 2017-06-09T00:28:45.925933Z

Which one? šŸ™‚

kenny 2017-06-09T00:29:14.929844Z

Latter

kenny 2017-06-09T00:29:36.932882Z

I just wanted to inspect the results of my rules after they had been ran.

kenny 2017-06-09T00:30:10.937570Z

It'd be cool to have a tool similar to re-frisk to visualize the current and past state.

alex-dixon 2017-06-09T00:31:24.947748Z

Is refrisk more tracing though? We were thinking something more similar to redux devtools

kenny 2017-06-09T00:33:24.964220Z

It is but I was thinking smaller steps šŸ™‚ Making your own redux devtools is quite ambitious šŸ™‚

alex-dixon 2017-06-09T00:34:45.975278Z

Hm. Ok. I hear you

alex-dixon 2017-06-09T00:35:12.978971Z

We could easily print out ā€œRetracted! xā€ ā€œAdded! yā€

kenny 2017-06-09T00:36:14.987155Z

As a first step, I think that'd be handy.

alex-dixon 2017-06-09T00:36:24.988559Z

Awesome

kenny 2017-06-09T00:37:35.997906Z

Also, not sure if you guys have a personal or company dev blog but posts about Precept would be great, especially if they were interactive with Klipse.

kenny 2017-06-09T00:38:22.003944Z

Of course that depends on how much time you guys have.. šŸ˜‰

alex-dixon 2017-06-09T00:51:36.104329Z

Sure. Tutorial type posts with examples is what you'd like to see?

šŸ’Æ 1
kenny 2017-06-09T17:35:33.751863Z

alex-dixon: App structure, talking to servers, debugging, testing

šŸ‘ 1
jfntn 2017-06-09T00:58:46.158018Z

mikegai: Interesting, how do you model the FSM concretely, is it a regular entity with facts?

2017-06-09T14:53:50.367Z

@alex-dixon You mentioned yesterday that you were thinking about rules without names, but it occurred to me this morning that might be difficult to resolve with dynamic loaders like Figwheel.

alex-dixon 2017-06-09T15:48:27.603846Z

@weavejester Correct. Weā€™re already facing an issue similar to that it seems. Page must be refreshed for rule changes to take effect https://github.com/CoNarrative/precept/issues/80

alex-dixon 2017-06-09T15:50:24.645765Z

You might notice define does not accept a name so we have already crossed this precipice for better or worse

2017-06-09T17:23:21.510536Z

@alex-dixon Couldnā€™t you give defines names as well?

alex-dixon 2017-06-09T17:26:00.561880Z

Yes though Iā€™m fairly confident the issue with having to refresh the page predated define having an autogenerated name

2017-06-09T17:26:48.577486Z

I guess if a rule is redefined, the associated session still has the old rules.

alex-dixon 2017-06-09T17:27:06.583250Z

Yes. Was just going to mention if you change the name of a rule you now have two rules

kenny 2017-06-09T17:58:00.200936Z

Any idea why a rule would return true after a fact has been retracted?

alex-dixon 2017-06-09T17:58:56.219687Z

Given what I just told weavejester I guess make sure you didnā€™t rename a rule šŸ™‚

alex-dixon 2017-06-09T17:59:23.228788Z

Is there another fact that could be satisfying the condition?

kenny 2017-06-09T18:01:09.267561Z

The fact simply isn't there. I am checking by printing the store.

alex-dixon 2017-06-09T18:01:57.284880Z

Ok. Would you be able to copy in the rule in question?

kenny 2017-06-09T18:02:23.293076Z

Sure. Lemme make an example. Still messing around with the example login form I sent yesterday.

alex-dixon 2017-06-09T18:02:35.297262Z

Cool

kenny 2017-06-09T18:06:13.374009Z

So the logging-in rule is being called every time the email or password inputs change.

alex-dixon 2017-06-09T18:06:31.380297Z

Ok. Taking a look

kenny 2017-06-09T18:07:30.400657Z

Just added the reagent component if that helps as well..

alex-dixon 2017-06-09T18:07:46.406140Z

Perfect. Was going to ask šŸ™‚

kenny 2017-06-09T18:09:06.432498Z

Ignore the duplicate rule.. šŸ˜†

šŸ‘ 1
alex-dixon 2017-06-09T18:11:26.479505Z

Hmā€¦.well. You might want :logging-in? to be :transient

kenny 2017-06-09T18:11:27.479943Z

So I never explicitly set :logging-in? to false but I do retract it.

alex-dixon 2017-06-09T18:11:34.482319Z

Not sure that will solve the problem

kenny 2017-06-09T18:11:43.485307Z

Well, the problem is do-login is async.

kenny 2017-06-09T18:12:15.495879Z

It technically should be :transient but all of the rules would run before that request completes.

kenny 2017-06-09T18:13:01.511529Z

I assumed it's not recommended to have a long-running synchronous function call in the RHS.

alex-dixon 2017-06-09T18:14:53.548745Z

I wouldnā€™t necessarily say that. I think it depends. Sometimes thatā€™s what you want. Maybe thatā€™s the case here?

kenny 2017-06-09T18:15:33.561103Z

Other things could be happening in the UI while that request is going through. Wouldn't that block the rules from continually running?

alex-dixon 2017-06-09T18:16:44.585885Z

This is true šŸ™‚

alex-dixon 2017-06-09T18:17:39.604884Z

When do you see the retraction happening

kenny 2017-06-09T18:18:26.621278Z

When it should -- after inserting :login-response.

kenny 2017-06-09T18:19:04.634267Z

But then everytime :email or :password changes from that point on, the logging-in rule is ran.

kenny 2017-06-09T18:19:25.641268Z

It's almost like it's stuck in a cache or something.

alex-dixon 2017-06-09T18:24:13.737506Z

And Iā€™m guessing :logging-in isnā€™t marked as :one-to-many in a schema

kenny 2017-06-09T18:24:37.744866Z

No.

kenny 2017-06-09T18:24:41.746325Z

No schema

kenny 2017-06-09T18:25:05.755622Z

(rules/session
  app-session
  'precept-play.rules)

alex-dixon 2017-06-09T18:25:47.770077Z

Ok

alex-dixon 2017-06-09T18:27:33.805821Z

Well, Iā€™m having a hard time seeing how ā€œlogging-inā€ is sticking around. Iā€™d suggest adding a rule that says ā€œif Iā€™m logged in Iā€™m not logging inā€

alex-dixon 2017-06-09T18:28:04.816347Z

I realize you have this with the response but Iā€™d try adding an additional rule for :logged-in?

kenny 2017-06-09T18:29:34.846559Z

Sorry, new rule or change to existing rule?

alex-dixon 2017-06-09T18:30:20.862444Z

Iā€™d add a new rule for it

kenny 2017-06-09T18:31:48.891906Z

Added this:

(rules/rule not-logging-in-when-logged-in
  [[_ :logged-in? true]]
  [[_ :logging-in? true]]
  =>
  (precept.util/retract! [:global :logging-in? true]))
And still getting the same problem.

alex-dixon 2017-06-09T18:31:52.893015Z

Oh

alex-dixon 2017-06-09T18:32:00.895849Z

Ok. Lightbulb

alex-dixon 2017-06-09T18:32:03.896628Z

Try

alex-dixon 2017-06-09T18:32:20.901844Z

[?fact <- [_ :logging-in? true]]

kenny 2017-06-09T18:33:32.926207Z

No slack clj highlighting šŸ˜¢

alex-dixon 2017-06-09T18:33:32.926420Z

For the login response rule add that line

alex-dixon 2017-06-09T18:33:38.928489Z

Yeah heh always forget

alex-dixon 2017-06-09T18:34:03.936733Z

But yeah try adding that line and retracting ?fact instead of the vector version of it

kenny 2017-06-09T18:34:28.944786Z

Worky!

alex-dixon 2017-06-09T18:34:31.945969Z

Yes!

kenny 2017-06-09T18:34:41.949357Z

Ok so why does my version not work?

alex-dixon 2017-06-09T18:35:00.955753Z

Well, it should first off. Sorry for your troubles šŸ™‚

alex-dixon 2017-06-09T18:35:36.967896Z

ā€œUnder the coversā€ all facts are Tuple records that have e a v fact-id, where fact-id is incremented for each fact added to the session

alex-dixon 2017-06-09T18:36:24.983767Z

So when retracting I think we do the same thing as inserting. If you supply a vector, we add that incremented fact id for you. So that gets passed to Claraā€™s retract, which happily retracts a fact that doesnā€™t exist

alex-dixon 2017-06-09T18:37:06.998075Z

The fact that does exist is the one in the session with that particular fact id, so you have to match on the whole thing in order to retract it

kenny 2017-06-09T18:37:39.009028Z

Makes sense.

alex-dixon 2017-06-09T18:37:54.013861Z

šŸ˜…

kenny 2017-06-09T18:39:04.037214Z

So using <- binds the whole tuple from the right hand side to the left?

alex-dixon 2017-06-09T18:39:39.048498Z

Yes. This is one of the ways our syntax is like Claraā€™s

kenny 2017-06-09T18:41:41.088860Z

Got it. Some more feedback for you guys.. I think an API should limit the number of ways you can do one thing as best as possible. So, I think retract!, insert!, etc. should all take a vector of facts rather than a single fact or a vector of facts.

alex-dixon 2017-06-09T18:43:32.125745Z

Ok. So for inserting a single fact youā€™d prefer (insert! [[id :bar "baz"]])?

kenny 2017-06-09T18:44:45.149623Z

Most definitely. It's slightly more verbose but far less obtuse.

kenny 2017-06-09T18:45:37.167394Z

As an example, Datomic's transact only takes a list of tx-data, never a single datom/map.

alex-dixon 2017-06-09T18:46:05.176322Z

Good example šŸ™‚

alex-dixon 2017-06-09T18:47:54.211865Z

Iā€™ve made a note. I made the decision based off my own laziness in response to Clara having insert!, insert-all!, insert-unconditional!, insert-all-unconditional!, insert and insert-all

kenny 2017-06-09T18:48:32.223893Z

IMO it's much better to just have one function that takes exactly one type of argument.

kenny 2017-06-09T18:50:03.253144Z

Yeah, that list of fns is nasty. My intuition tells me that the author did that for some sort of performance reasons. Not sure if that is true or not.. šŸ™‚

alex-dixon 2017-06-09T18:51:46.286405Z

I think youā€™re right. Thanks for the feedback that makes a lot of sense to me

alex-dixon 2017-06-09T18:52:28.300030Z

Also I just came across your spectomic library. Thanks for making that, speaking of something thatā€™s been bugging me šŸ™‚

kenny 2017-06-09T18:53:50.325118Z

I'm surprised you found that actually

alex-dixon 2017-06-09T18:55:15.352962Z

I think me and everyone else have been looking for it for some time now šŸ˜„

kenny 2017-06-09T18:56:56.386437Z

Haha maybe. It wasn't clear to me if that was the right solution. I wanted to give it some time internally to see if it actually shakes out well.

alex-dixon 2017-06-09T18:58:42.421315Z

Iā€™ve heard it mentioned more than once that people would like the two to converge or be compatible in some way

alex-dixon 2017-06-09T18:59:00.426614Z

Oh ok. I was going to ask if youā€™d mind if I tweeted about it šŸ™‚

kenny 2017-06-09T19:00:27.456371Z

My main concern was the inherent coupling you make between app level specs and Database schema. Maybe that's the way things typically shake out, maybe not ĀÆ\(惄)/ĀÆ

kenny 2017-06-09T19:00:42.461628Z

But yeah you can šŸ™‚

kenny 2017-06-09T19:01:01.468207Z

What is your Twitter name?

alex-dixon 2017-06-09T19:01:12.471826Z

@a_dixon

alex-dixon 2017-06-09T19:01:26.476717Z

Iā€™m very creative šŸ™‚

kenny 2017-06-09T19:06:04.563974Z

Anyway, why are rules named? Is it only for documentation purposes?

alex-dixon 2017-06-09T19:07:17.586460Z

Was talking to weavejester about this earlier. Weā€™d prefer them not to be but managing that is a little tricky and I ran out of time

kenny 2017-06-09T19:09:30.626325Z

Ah, yes I see that. Yeah, that definitely seems like something that should be figured out. Consistency is important šŸ™‚

alex-dixon 2017-06-09T19:11:03.654176Z

Yeah. define seems to be working. There are some larger issues that weā€™d like to solve there like not multiplying rules when you rename them and not having to refresh the page for a change to a rule to take effect

alex-dixon 2017-06-09T19:11:21.659699Z

I think you opened the issue for that yesterday

kenny 2017-06-09T19:11:26.660998Z

Right, right.

kenny 2017-06-09T19:11:42.665622Z

Though, I think a name and/or a docstring would be important to have as well

alex-dixon 2017-06-09T19:12:18.676081Z

Would you be ok with no names but allow docstrings? For all our macros

2017-06-09T19:13:15.692883Z

I think if thereā€™s no names, there should be a way of grouping rules, perhaps.

2017-06-09T19:13:55.704579Z

Itā€™s a shame that Clara Rules doesnā€™t have anonymous rules. The code makes it look like thatā€™s certainly possible.

2017-06-09T19:14:50.720391Z

(def my-session
  (precept/session
   (precept/rule [...] => [...])))

captainlexington 2017-06-09T19:15:13.727302Z

That would be a very pretty API

2017-06-09T19:16:32.751171Z

Or maybe:

(def my-session
  (precept/session
   ([...] => [...])))

kenny 2017-06-09T19:17:05.760208Z

Is there a reason you suggest embedding rule inside session? I'd think that having a defrules macro might be cleaner. Then you'd pass that symbol created by defrules to session's opts.

kenny 2017-06-09T19:17:29.767032Z

You could also have grouping with defrules.

2017-06-09T19:17:49.773022Z

My understanding is that you have rules, and groupings of rules called sessions.

kenny 2017-06-09T19:18:27.784141Z

Is there any reason rules couldn't be reused across sessions?

2017-06-09T19:19:16.798276Z

They could, but then youā€™d write:

(def my-rule
  (precept/rule [...] => [...]))

(def my-session
  (precept/session my-rule ...))

2017-06-09T19:19:43.806326Z

If rules are first-class you could just assign a var to them.

2017-06-09T19:20:11.814570Z

And the linking between sessions and rules would use Clojureā€™s normal require mechanism

2017-06-09T19:20:15.815927Z

So it should be reload-safe.

kenny 2017-06-09T19:20:33.821320Z

LGTM. Could have defrule as a shortcut as well.

2017-06-09T19:20:54.827269Z

Right šŸ™‚

2017-06-09T19:21:53.844356Z

But Clara Rules has some odd complexity that seems unnecessary

2017-06-09T19:21:57.845376Z

(defmacro defrule
  [name & body]
  (let [doc (if (string? (first body)) (first body) nil)
        body (if doc (rest body) body)
        properties (if (map? (first body)) (first body) nil)
        definition (if properties (rest body) body)
        {:keys [lhs rhs]} (dsl/split-lhs-rhs definition)

        production (cond-> (dsl/parse-rule* lhs rhs properties {})
                           name (assoc :name (str (clojure.core/name (com/cljs-ns)) "/" (clojure.core/name name)))
                           doc (assoc :doc doc))]
    (add-production name production)
    `(def ~name
       ~production)))

2017-06-09T19:22:14.850051Z

The def part in the macro could just be removed

2017-06-09T19:22:39.857720Z

I think šŸ™‚

alex-dixon 2017-06-09T19:22:45.859381Z

I think thereā€™s dsl/parse-rule that does that

alex-dixon 2017-06-09T19:23:07.865506Z

In clara

2017-06-09T19:24:09.883906Z

Ahh, thanks @alex-dixon

2017-06-09T19:25:38.910876Z

As far as I can tell, the extra stuff in defrule is to set the docstrings, etc, and to add all the rules to a place where they can be loaded per namespace

2017-06-09T19:26:54.933319Z

And loading per namespace is convenient, butā€¦

2017-06-09T19:27:12.938696Z

Kinda makes reloading hard.

alex-dixon 2017-06-09T19:27:29.943924Z

I think mk-session accepts a list of ā€œproductionsā€ that may be rules http://www.clara-rules.org/apidocs/0.15.0/clojure/clara.rules.html#var-mk-session

alex-dixon 2017-06-09T19:27:50.950096Z

Like dsl/parse-rule itā€™s CLJ only

2017-06-09T19:30:00.987863Z

Hm. It looks like the rules are only available at compile-time to the Clojure compiler.

alex-dixon 2017-06-09T19:30:08.990368Z

;; Store production in cljs.env/*compiler* under ::productions seq?
(defn- add-production [name production]
  (swap! env/*compiler* assoc-in [::productions (com/cljs-ns) name] production))

(defn- get-productions-from-namespace
  "Returns a map of names to productions in the given namespace."
  [namespace]
  ;; TODO: remove need for ugly eval by changing our quoting strategy.
  (let [productions (get-in <@U095WMJNR>/*compiler* [::productions namespace])]
    (map eval (vals productions))))

(defn- get-productions
  "Return the productions from the source"
  [source]
  (cond
   (symbol? source) (get-productions-from-namespace source)
   (coll? source) (seq source)
   :else (throw (IllegalArgumentException. "Unknown source value type passed to defsession"))))

alex-dixon 2017-06-09T19:30:25.995442Z

Theyā€™re also doing this for CLJS I think

alex-dixon 2017-06-09T19:30:49.002386Z

This is the top of clara/macros.clj

2017-06-09T19:32:11.026307Z

Yeah, so the rules are defined and assembled in Clojureā€¦ I think

alex-dixon 2017-06-09T19:33:37.051081Z

I think Clojurescriptā€™s eval has matured to the point where that might not be necessary

2017-06-09T19:34:00.057656Z

Including ClojureScriptā€™s eval adds a whole lot of overhead to the compiled JS

alex-dixon 2017-06-09T19:34:18.062851Z

Like the entire compiler?

2017-06-09T19:34:19.062981Z

Because it effectively needs to include all of the ClojureScript compiler.

2017-06-09T19:34:22.064086Z

Yeah.

2017-06-09T19:34:36.067870Z

Otherwise Closure just excludes all that.

alex-dixon 2017-06-09T19:34:42.069583Z

Hm. Ok

alex-dixon 2017-06-09T19:35:28.083306Z

Even with this one? https://cljs.github.io/api/cljs.js/eval

2017-06-09T19:35:42.087194Z

It looks like Clara Rules operates a little like core.match, in that you have a bunch of rules that are evaluated at compile time into Clojure code.

2017-06-09T19:36:10.094983Z

@alex-dixon Pretty sure any eval in your ClojureScript means you need all the compiler stuff.

2017-06-09T19:36:38.103166Z

I guess it would be easy to check

alex-dixon 2017-06-09T19:40:51.174614Z

Iā€™ve found Mike Fikes to be an expert in this area

alex-dixon 2017-06-09T19:42:44.207700Z

I canā€™t tell if heā€™s saying Planck can eval Clojurescript in Javascript http://blog.fikesfarm.com/posts/2016-01-22-clojurescript-eval.html

2017-06-09T19:47:34.291215Z

Iā€™m just checking the sizesā€¦

2017-06-09T19:48:13.302182Z

79K without, 1.1M with. Assuming Iā€™ve done it right.

alex-dixon 2017-06-09T19:48:27.306245Z

Yikes

alex-dixon 2017-06-09T19:48:33.308186Z

Thanks for doing that

2017-06-09T19:48:57.315066Z

np

2017-06-09T19:49:07.317613Z

For reference, I compared:

(ns cljseval-test.core
  (:require [cljs.js :refer [empty-state eval]]))

(eval (empty-state) '(println "x") identity)

2017-06-09T19:49:22.321930Z

To:

(ns cljseval-test.core)

(println "x")

2017-06-09T19:49:38.326376Z

With eval it was 1.1M, without 79K.

captainlexington 2017-06-09T19:50:16.337398Z

šŸ˜¢

2017-06-09T19:50:35.343239Z

I think I get what Clara Rules is doing now.

2017-06-09T19:51:53.366042Z

Without its custom registry, youā€™d have to define all the rules together, the same as core.match. Perhaps the authors wanted to leverage namespaces.

2017-06-09T22:09:41.364699Z

I have a few thoughts on the rules setup

alex-dixon 2017-06-09T22:10:09.369391Z

!

alex-dixon 2017-06-09T22:10:11.369667Z

šŸ™‚

2017-06-09T22:10:40.374784Z

Iā€™m not sure how good these will be. They might be half-baked šŸ™‚

2017-06-09T22:12:00.388003Z

So my understanding of the ClojureScript implementation of Clara Rules is that the rules themselves barely touch ClojureScript. Theyā€™re defined in Clojure, shoved into the compiler environment, then consumed by the session. They donā€™t really exist inside of ClojureScript per se.

2017-06-09T22:13:09.399083Z

Because they donā€™t really map to vars, I wonder if itā€™s worth considering a different registry. When clojure.spec was created, the decision was made not to overload vars and namespaces, and to create a separate registry for specs.

2017-06-09T22:13:32.402706Z

As compile-time artifacts, I wonder if itā€™s worth looking at rules in the same light.

2017-06-09T22:14:06.408731Z

So:

(p/defrule ::todo-is-visible
  [[_ :visibility-filter :active]]
  [[?e :todo/done false]]
  =&gt;
  (p/insert! [?e :todo/visible true]))

2017-06-09T22:15:04.418218Z

Using a keyword as the identifier over a symbol would indicate that the rules are not vars in the usual sense. Behind the scenes, perhaps it maps out to something likeā€¦

2017-06-09T22:17:26.441800Z

(swap! env/*compiler* assoc-in [::registry ::todo-is-visible]
      [:rule '([[_ :visibility-filter :active]]
               [[?e :todo/done false]]
               =&gt;
               (p/insert! [?e :todo/visible true])])])

2017-06-09T22:18:41.453988Z

So just take the data verbatim and stuff it in a registry. Essentially keep all the rules as data until theyā€™re passed into the session and constructed into an opaque block of code.

2017-06-09T22:19:27.461559Z

Internally Clara Rules might do this - not sure - but Precept adds some additional stuff like subs, so it might be worth keeping everything as compile-time data.

2017-06-09T22:19:36.462995Z

Alternatively:

2017-06-09T22:20:13.468999Z

(swap! env/*compiler* assoc-in [::registry :rules ::todo-is-visible]
      '([[_ :visibility-filter :active]]
        [[?e :todo/done false]]
        =&gt;
        (p/insert! [?e :todo/visible true])])])

2017-06-09T22:22:08.487542Z

When creating the session we should be able to do it anonymouslyā€¦

šŸ‘ 1
2017-06-09T22:22:54.495105Z

From my reading of clara.macros anyway.

2017-06-09T22:24:38.511792Z

So maybe something like:

(def session
  (p/session :rules [:*] :subs [:example.subs/*]))

2017-06-09T22:25:09.516830Z

Could use some kind of basic pattern matching to restrict the rules used in the session.

2017-06-09T22:25:22.518979Z

:* - any rule, maybe the default

2017-06-09T22:25:38.521335Z

:namespace/* - any rule in a namespace

2017-06-09T22:25:47.522795Z

:namespace/name - specific rule

2017-06-09T22:27:17.537588Z

I think it might still be worth identifying rules somehow, because it both documents and provides a degree of uniqueness.

2017-06-09T22:28:56.553036Z

The general idea is to draw a clear dividing line between whatā€™s set up at compile time (the rules registry), and whatā€™s set up at runtime (the session).

jfntn 2017-06-09T22:34:37.606394Z

This kind of registry has been successful for spec, and in a more similar context re-frame as well. It also seems like this can be implemented without changing clara, which goes some way towards making the rules engine more pluggable?