Fork me on GitHub
#clara
<
2017-08-06
>
mrchance00:08:47

@mikerod hm, ok. Idempotency shouldn't be an issue, good hint though. Gonna try that, although I am not 100% clear on how you mean that. In my use case, there would be rules that produce a [Linked a b] fact which would call something like core.async/pipe on a and b, only it returns something that can be called or closed when the respective Linked fact goes away in order to sever the connection again. How would I address that using :not rules?

mrchance00:08:44

Clara is awesome btw. ! Played with it a bit more in the meantime

mikerod00:08:35

@mrchance an alternative that comes to mind is to hook into Clara’s listeners to try to watch for the particular retraction you are interested in. However, I’d probably say it is best if that isn’t necessary.

mikerod00:08:52

I hate to suggest things like insert-unconditional! but I see an approach with that at least…

mikerod00:08:01

I’d like to think of something better though

mrchance00:08:06

Yeah, I saw the ns in the docs and thought about that

mikerod00:08:17

(defrule makes-chan
  [?a <- A]
  [?b <- B]
  =>
  (let [chan (somehow-make it)]
    ;; Not sure what you do with `chan` here
    (r/insert! (->LogicalThing ?a ?b))
    (r/insert-unconditional! (->OpenedChan chan))))

(defrule closes-chan
  [:not [LogicalThing]]
  [?oc <- OpenedChan (= ?chan chan)]
  =>
  (r/retract! ?oc)
  (close-the ?chan))

mikerod00:08:36

I think it just gets sort of dirty when you are managing your own unconditional facts and retracts - typically a pattern to avoid

mikerod00:08:06

not sure how prevalent this would be for you though in terms of managing it. also, not positive my solution is really a solution to the issue at all

mrchance00:08:11

Ok, I can see what you're getting at, but I agree it looks suboptimal

mikerod00:08:25

Clara has a listener protocol you can attach onto

mikerod00:08:33

and I believe you can find the relevant retract events there

mikerod00:08:44

not sure there have been docs posted up on that

mrchance00:08:24

Not many, from what I browsed yet 😉

mikerod00:08:19

The ITransientEventListener

mikerod00:08:01

even when looking at this though, I think it is perhaps opaque which retraction you’d want to listen to

mrchance00:08:48

Hm, maybe. I'll give it a try

mikerod00:08:51

I believe (retract-facts! [listener facts]) & (retract-facts-logical! [listener node token facts]) would have the info

mikerod00:08:15

retract-facts! I believe is retracts from the RHS and retract-facts-logical! is retracts from truth maintenance

mikerod00:08:25

other “retract” things I believe are more internal node-to-node activity

mrchance00:08:03

Thanks! I'll test it

mikerod00:08:17

(mk-session rules :listeners [my-listener-impl])

mrchance00:08:23

I think there is some big potential here, like a completely reactive description of stateful systems, something that's always awful when it moves past what e.g. component can handle

mrchance00:08:41

That's simple enough 😉

mikerod00:08:50

yeah, it isn’t actually documented on mk-session, not sure why. I don’t think those ns’s are really called “experimental” around this at this point

mikerod00:08:12

the only thing I’m concerned about is if you do not impl all the functions of the protocol

mikerod00:08:19

I can’t remember if you have to “pad” those with a no-op in some way

mrchance00:08:19

Typical case of documentation not growing as fast as its software

mrchance00:08:58

Shouldn't be a problem, it's a one time thing so some boilerplate is no issue

mikerod00:08:09

there is the clara.rules.listener/default-listener though

mikerod00:08:15

you could just delegate everything else through that

mikerod00:08:23

but it’s just a no-op

mikerod00:08:48

yeah, idk. I’ve done stuff with this before too. I just can’t remember

mrchance00:08:53

Ok, then actually delegating is probably more work ;)

mikerod00:08:06

I could have swore there was a smoother way

mrchance00:08:49

I think this one is good enough, if it works

mikerod00:08:55

> I think there is some big potential here, like a completely reactive description of stateful systems, something that’s always awful when it moves past what e.g. component can handle That is cool though

mikerod00:08:12

would be interesting to hear what success you have with that

mrchance00:08:31

Sure, I'll let you know

mikerod01:08:48

btw, looks like precept uses Clara :listeners when I did a quick GitHub search

mikerod01:08:05

I knew they were doing interesting things in using Clara for app state mgmt (may be saying that wrong)

mrchance01:08:12

Right, I stumbled across that too

mikerod01:08:36

they impl’ed the protocols though and included the no-ops

mrchance01:08:09

Probably going to have a look into their code, I like the idea of precept as well

mikerod01:08:31

yeah, I’ve wanted to look at that codebase sometime soon

mikerod01:08:37

seems like some interesting stuff

wparker05:08:16

Several people have had use cases that sounded like what they were looking for was the ability to get the changes in query results relative to an earlier state, and it sounds like that sort of functionality might be what you’re looking for as well @mrchance . That could be done with some wrappers in your code around the session along the lines of “Query the session, store the results, insert/retract facts, fire the rules, then query again and diff the results”. It could be done as a Clara listener too by tracking on the listening calls in QueryNode: https://github.com/cerner/clara-rules/blob/0.15.2/src/main/clojure/clara/rules/engine.cljc#L430

wparker05:08:17

It is functionality that I think would be useful for Clara itself to provide at some point, a listener to do that would probably get into Clara’s internal impl details somewhat e.g. “is this node a QueryNode?” logic. Wouldn’t matter if it was part of Clara and tested there though.

mrchance13:08:00

@wparker True, that's another way to look at it. This might work too. Your answer also makes me wonder if Datascript would be the better choice for this usecase though, since there you get the transaction logs anyway

wparker14:08:52

I haven’t had occasion to use DataScript, but it also seems like something that could be useful for a use-case like what you describe @mrchance . I suspect much depends on what the simplest way to model the logic you have in mind is and what performance characteristics you’re looking for.

mrchance17:08:37

Yes, it all depends on the details. From the FactUi readme it looks like they took a bit from both worlds as well