clara

http://www.clara-rules.org/
amarjeet 2017-12-27T10:59:15.000014Z

When i inspect a session, the value of :fact->explanations key is always nil, despite facts being inserted into the session. My goal is to check what all facts are in the session. Help? CC: @mikerod

amarjeet 2017-12-27T11:03:16.000204Z

The session->fact-graph too returns nil: {:forward-edges {}, :backward-edges {}}

2017-12-27T14:59:25.000376Z

@amarjeet I think I’d need more of an example to see what you mean

2017-12-27T15:00:05.000152Z

However, if you are just doing this for some sort of debugging, you could also add a query that matched any fact and use that to see what is in the session. This query could be a performance issue in a production usage though,.

amarjeet 2017-12-27T15:04:46.000107Z

I was trying to inspect mysession.

amarjeet 2017-12-27T15:05:14.000313Z

I was debugging basically, so with queries I can test things

amarjeet 2017-12-27T15:05:52.000381Z

in the process of debugging, I tried inspect and fact-graph...thats when I came across nil values

amarjeet 2017-12-27T15:06:58.000191Z

But, queries clearly shows that facts are there. So, now just wondering if :fact-explanation or fact-graph should be looked at or not?

2017-12-27T15:28:13.000334Z

@amarjeet your code snipet looks wrong. Perhaps just a typo? You have (insert-all facts base-session) when it should be (insert-all base-session facts) - base-session is first arg

2017-12-27T15:32:10.000016Z

Also, I only see 2 def in your example. One for base-session and one for mysession. I don’t see what you called to try inspecting and looking at the inspection results. That’d be useful too. Pending the above comment I had was just a typo

amarjeet 2017-12-27T16:02:09.000047Z

My bad on the mistake in mysession def. Modified the code snippet. Added the inspect fun call.

2017-12-27T16:03:03.000287Z

@amarjeet did you call fire-rules on the mysession?

amarjeet 2017-12-27T16:04:30.000226Z

no actually

amarjeet 2017-12-27T16:04:59.000376Z

I see thats the problem? Because, I just tried with fire-rules, and I see the facts

amarjeet 2017-12-27T16:06:03.000152Z

But, without firing the rules, the insertion is happening

amarjeet 2017-12-27T16:07:03.000290Z

with fire-rules, only matched facts are being returned under the fact->explanation

amarjeet 2017-12-27T16:07:31.000398Z

I thought, with inspect, I could see all inserted facts, not just the matched ones

2017-12-27T16:10:53.000302Z

@amarjeet I think in general you shouldn’t assume much about the state of working memory prior to fire-rules

2017-12-27T16:11:10.000280Z

Take that as a general principle. Things are done sometimes “lazily” in some respects

2017-12-27T16:11:36.000014Z

That doesn’t answer the 2nd part of your question as to what is missing post-rule firing though

amarjeet 2017-12-27T16:14:38.000164Z

hmm, understood the issue now regarding 'before fire-rule' part.

amarjeet 2017-12-27T16:20:59.000358Z

I re-checked, post fire-rules, I can see only matched facts, not all inserted ones (in that session)

2017-12-27T16:32:28.000141Z

I’ll have to take a look at things a bit to have a better answer on that

amarjeet 2017-12-27T16:33:42.000260Z

cool cool, thanks much

2017-12-27T17:10:14.000039Z

@amarjeet it seems the purpose of the key :fact->explanations is to explain derived facts within working memory

2017-12-27T17:10:25.000017Z

not facts explicitly given via an external insert or insert-all

amarjeet 2017-12-27T17:10:57.000168Z

okay, that makes sense then

2017-12-27T17:11:00.000069Z

You can dig out that info in some sense

amarjeet 2017-12-27T17:11:13.000214Z

yeah

2017-12-27T17:11:28.000148Z

Take for example:

:fact->explanations
{#clara.test_rules.B{}
[{:rule {:ns-name clara.test-rules, :lhs [{:type clara.test_rules.A, :constraints []}], :rhs (do (insert! (->B))), :name "clara.test-rules/test-a"},
:explanation #clara.tools.inspect.Explanation{:matches ({:fact #clara.test_rules.A{}, :condition {:type clara.test_rules.A, :constraints []}}), :bindings {}}}]}

2017-12-27T17:11:53.000024Z

clara.test_rules.B is the derived fact

2017-12-27T17:12:24.000232Z

the value under it is a list of rules deriving it. There’d be more than one if multiple of these facts were = in working memory.

amarjeet 2017-12-27T17:13:41.000161Z

yes, I did got that when I checked with fire-rules

amarjeet 2017-12-27T17:13:54.000029Z

understood it now

2017-12-27T17:14:46.000136Z

(into []
      (comp cat
            (map :explanation)
            (mapcat :matches)
            (map :fact))
      (vals (:fact->explanations inspect-results)))
combined with (keys (:fact->explanations inspect-results)) sort of gets you there

2017-12-27T17:15:14.000299Z

Also, an important consideration is that Clara doesn’t hold references to any inserted facts that cannot contribute to any rule

2017-12-27T17:15:26.000218Z

So those effectively are not in working memory at all anymore

amarjeet 2017-12-27T17:15:57.000448Z

hmm, yeah, got it

amarjeet 2017-12-27T17:16:14.000140Z

makes sense now

2017-12-27T17:16:18.000056Z

(defrecord A [])

(defrule not-using-a
  [:not-a]
  =>
  (insert! {:not-a true}))

(-> (mk-session [not-using-a])
    (insert (->A))
    fire-rules)

2017-12-27T17:16:29.000362Z

you’d find no references to A fact instance in working memory at all

2017-12-27T17:16:55.000046Z

@alex-dixon has done some more interesting things with session inspection I believe. He may have thoughts on this though.

2017-12-27T17:17:49.000145Z

On the topic of analyzing all facts inserted or that sort of thing. Then again, for dev only, if you are using the typical type hierarchy you could just do

(defquery find-any-fact []
   [?f <- Object])

amarjeet 2017-12-27T17:20:12.000212Z

yeah, this testing trick works, I tried testing with different types of queries.

alex-dixon 2017-12-27T17:24:03.000135Z

Example of abusing clara.listeners 😊

alex-dixon 2017-12-27T17:29:42.000364Z

It’s a tremendously well designed interface. This is just one implementation. We set up a core async pipeline to process insertions from outside the session (see in precept.core if interested). Each time there’s an insert we add and remove a listener and divide the listener ops into additions and removals

alex-dixon 2017-12-27T17:31:20.000293Z

From there we apply the ops to an atom that represents “current state”

alex-dixon 2017-12-27T17:34:04.000352Z

Part of motivation over a query is that queries become part of the rete network so having one that matches on everything wasn’t performant

👍 1
alex-dixon 2017-12-27T18:27:35.000173Z

@amarjeet Just making sure you saw this in case it might be helpful

amarjeet 2017-12-27T18:28:51.000239Z

oh, just saw, gonna look at it

amarjeet 2017-12-27T18:29:02.000165Z

thanks 🙂

👍 1