clara

http://www.clara-rules.org/
2018-01-19T15:04:07.000545Z

@dave.dixon I mostly never would recommend many patterns that make pervasive use of insert-unconditional!

2018-01-19T15:05:12.000933Z

The one case I keep seeing that is difficult to work around is when needing to retract internally for something like “old events”. Other than that, I think it’s best to avoid. Even then, there are several RHS retract related issues outstanding that can be seen in the GitHub

2018-01-19T15:05:28.000554Z

I’m looking at your example to see if I see anything you could do

2018-01-19T15:37:25.000155Z

Perhaps something like this @dave.dixon

2018-01-19T15:41:20.000378Z

Woops missing a part in that, will edit

1
sparkofreason 2018-01-19T15:58:07.001020Z

@mikerod Interesting. Let me ponder that.

2018-01-19T15:59:28.000570Z

I am missing a part still. Trying to get that done. The concept I think can work though in terms of marking a timestamp at each stage. However, the above fails because it is letting TMS remove the intermediary collections from previous runs

2018-01-19T16:00:14.000424Z

I think you have to signal each “stage” as an explicit fact though. Without something like that, the network never knows what each conceptual step is to you. It doesn’t distinguish one fire-rules from another really

2018-01-19T16:00:34.000619Z

So usually when that sort of info is missing, you end up adding it as a fact to represent the idea

2018-01-19T16:52:34.000528Z

@dave.dixon I updated it now

2018-01-19T16:53:09.000084Z

It is hard to say that it exactly captures what you want. If you look at :before-retract though, you get the multiple accumulated groups idea that you were wanting

2018-01-19T16:53:23.000420Z

Just requires each fact to be externally stamped with the same “timestamp” as the “fire event” that they were inserted with

2018-01-19T16:53:34.000327Z

I couldn’t work out a way for rules to express that stamping due to logical TMS.

2018-01-19T16:53:55.000180Z

Retracting is slightly harder, since you need to retract all matching facts across all timestamps (at least from your sort of example)

2018-01-19T16:54:21.001006Z

This retraction results in all prior groups being updated as well to remove the fact that is gone. That isn’t exactly what you wanted I dont’ think, but it conveys somewhat similar information.

2018-01-19T16:57:32.000568Z

The accumulation for Nums could tag it with the FireEvent ts it went with. Then that could be used to do a duplicate removal and/or “newest” result lookup on the :before-retract vs :after-retract

sparkofreason 2018-01-19T17:42:17.000293Z

I think I was probably just going about things in the wrong way. The above is an example of how I'm modeling interaction with the outside world, where we logically insert Request facts when business logic dictates. The outside will unconditionally insert a response correlated with that request, and then the response rule does a logical insert of the updated business object derived from the response. Works fantastic, and serves as sort of a dynamic API. The place where it falls down is if you try to make a request that depends on an accumulated result, e.g. RequestCompleteAll, which depends on accumulating the current todo's which are not done. But then updating the todo's as done results in a logical contraction, hence my desire for the behavior described in my original example. But I'm now thinking the way to accomplish this would be to just aggregate over the requests, no the todos, and it would be the responsibility of the client code to just supply all of the associated responses. The reasoning is that this "works" because the rule that aggregates the requests does not do a logical insert, but just publishes the appropriate aggregate of requests to the client.

2018-01-19T18:57:55.000579Z

@dave.dixon Perhaps a model like the following might work if you’re OK with accumulating some “garbage” over time.

- Logically insert a "Request" fact.
- Have a query like [Request (= ?id id)] [:not [RequestResponse (= ?id id)]].
- The client would externally insert a RequestResponse fact when it wanted to "close" a request.
- A todo could be done like [Request (= ?id id)] [:not [RequestResponse (= ?id id)]] => (insert! (->ToDo ?id)).
Then further logic downstream could dispatch on the TODOs as required, say if too many were outstanding.
If you need to clean up garbage, it almost sounds like you’re asking about retracting a fact without removing downstream insertions due to it.. is that on target at all?

sparkofreason 2018-01-19T19:28:19.000106Z

@wparker I think in your 4th bullet you would remove the :not. But otherwise, that's basically it. The "garbage" is okay, I'm experimenting with rulesets that enforce logical consistency over time, e.g. of some process of interacting with the user and an external server. So the "garbage" is really the history. What I'm finding is that you generally have some "anchor" facts from which the rest of the process logic flows, so when you change the anchor the "garbage" gets collected. For example, in the conduit example, an anchor fact is the filter which retrieves a set of articles from the server, So articles wind up inserted with conditional dependence on the filter fact. Then the user can do a number of things, like change the favorite status of an article, edit if they are the author, etc. So all of that history gets accumulated, but when you change the filter it's all retracted.

sparkofreason 2018-01-19T19:32:19.000068Z

@wparker It wasn't specifically that I was looking to retract a fact without removing downstream insertions, rather modify the set of facts that went into an accumulator without retracting downstream insertions created by previous activations of the accumulator rule. It makes sense from a purely logical standpoint (I think), but the semantics of accumulators in the rule network are slightly different - not wrong, just making a different logical assertion, and one that is feasible within rule network architecture.