clara

http://www.clara-rules.org/
dominicm 2018-05-19T06:14:03.000060Z

@mikerod I can't seem to create a minimal repro of this, which leaves me more confused.

dominicm 2018-05-19T06:15:50.000019Z

{:?fact #roll_altc.LaunchConfigurationFact{:e #roll_altc.LaunchConfiguration{:id "app", :qualifier nil},
                                            :a :roll/created-for,
                                            :v #roll_altc.ASG{:id "app", :qualifier nil}},
  :?by #roll_altc.LaunchConfiguration{:id "app", :qualifier nil},
  :?for #roll_altc.ASG{:id "app", :qualifier nil}}
I definitely have this in my results though, which I just can't grasp.

dominicm 2018-05-19T06:20:57.000075Z

I added a prn to do some debugging, and if I refer to ?for I get: > Using variable that is not previously bound. This can happen when an expression uses a previously unbound variable, or if a variable is referenced in a nested part of a parent expression, such as (or (= ?my-expression my-field) ...). I'm guessing this is suggesting that ?for is unbound, which is weird, but does explain what I am seeing.

dominicm 2018-05-19T06:23:43.000062Z

I get that in the minimal case where it works too, so I guess that's not it.

dominicm 2018-05-19T06:32:50.000005Z

> A parameter definition, which allow callers to control the scope of the query when it is called. Makes me think that params should be bound when queries start, but instead it seems like they're unbound, and filtered at the end. Is that true?

dominicm 2018-05-19T18:55:59.000057Z

(defquery created-for-e
  [:?e]
  [RollCreatedFor (= e ?e) (= ?v v)])
Is there a reason that :?e is optional, when I execute this query without an :?e I get no results, I thought it might be like in datalog rules where it would be treated as an unbound variable in that case.

alex-dixon 2018-05-19T18:59:40.000042Z

Maybe bound to nil?

alex-dixon 2018-05-19T19:06:14.000025Z

@dominicm are you using the with meta eav pattern? Also curious if you’re using def session or mk session and how you’re defining rules...I forget whether there’s any potential pitfalls with reloading them in clj

dominicm 2018-05-19T19:13:40.000009Z

@alex-dixon I'm onto "namespace d" now, where I'm trying (defrecord AWSDBType [e v]) and (defrecord AWSDB [id qualifier])

dominicm 2018-05-19T19:18:14.000074Z

I have experimented with 4 approaches now 🙂

alex-dixon 2018-05-19T19:18:40.000061Z

What’s not working? Sorry kind of got lost

dominicm 2018-05-19T19:19:37.000085Z

Oh, in the original question you mean? I was getting the ASG in the results, when I was specifying :?for as (->DBBox "main" nil)

alex-dixon 2018-05-19T19:22:01.000023Z

Oh ok. Is there anything you’re stuck on still?

dominicm 2018-05-19T20:06:23.000074Z

I'm still confused as to why I'm having issues with the query https://clojurians.slack.com/archives/C08TC9JCS/p1526681740000082 but I'm unable to create a minimal reproducible.

dominicm 2018-05-19T20:09:11.000108Z

But otherwise, I'm doing okay. I think I've got a grip on this generally though.

dominicm 2018-05-19T20:48:13.000091Z

(defrule DatabaseBox-Engine
  [?dbi <- AWSDBInstance]
  [?dbox <- DatabaseBox]
  [RollCreatedFor (= e ?dbi)]
  [DatabaseBoxEngine (= e ?dbox) (= ?v v)]
  =>
  (insert!
    (->AWSDBInstanceEngine ?dbi ?v)))
This inserts 2 AWSDBInstanceEngine rules, I think I understand why, it's due to how the dataset is being queried. Do rule engines / Does clara provide anything around stopping the insertion of facts twice here? I'm quite happy to "defend" on the LHS, rather than attempt to deduplicate on the RHS. I'm somewhat trying to avoid having to figure out conflict resolution in my final state.

2018-05-19T21:17:14.000058Z

@dominicm I haven’t been able to look at anything today. I can quickly answe your last question though: Clara doesn’t try to prevent duplicates. That’s up to your logical structuring. You can often do something like an accumulate all sort of rule to “de dupe “ or aggregate your duplicate facts and choose how to merge it. So you’d let some “intermediate type” be duplicated but have some downstream aggregate/merged type result from them and then be used in subsequent rules

2018-05-19T21:18:08.000090Z

It’d be interesting to have a mode for Clara to prevent duplicates. However there are practical use cases for actually wanting duplicates too. So the default I feel is sane. Think something about logic that cares about cardinality of matches etc. Also removing duplicates tends to be performance overhead.

dominicm 2018-05-19T21:21:50.000046Z

@mikerod yeah, I actually want the many cardinality in some cases. I was hoping there might be a way to structure the rule such that there was no duplicates in the query.

2018-05-19T21:24:18.000043Z

I could give good example if not on phone. Hah

alex-dixon 2018-05-19T21:24:41.000090Z

(defrule DatabaseBox-Engine
  [?dbi <- AWSDBInstance]
  [?dbox <- DatabaseBox]
  [RollCreatedFor (= e ?dbi)]
  [DatabaseBoxEngine (= e ?dbox) (= ?v v)]
[:not AWSDBInstanceEngine ?dbi ?v]
Maybe something like this? Sry on phone also

2018-05-19T21:24:48.000034Z

I tend to just let the rules insert duplicates. But make it a intermediate fact type. Then have a single rule that aggregates it.

2018-05-19T21:25:12.000090Z

There are negation patterns too. Like @alex-dixon just said. You just have to watch out for making a logical infinite loop

1👍
2018-05-19T21:28:56.000027Z

Defrule example

Lhs Logic

=>

Insert IntermediateThing data from rule

Defrule aggregate-dups 

?all <- acc/all :from IntermediateThing (= ?id is)

=>

Insert RealThing (merge-somehow ?all)

1👍
2018-05-19T21:29:16.000018Z

Pseudo code

dominicm 2018-05-19T21:36:27.000082Z

Appreciate the help here. I'll take a shot at this tomorrow

alex-dixon 2018-05-19T21:38:14.000005Z

Nb I think my example above would loop with insert logical, not if you were to use insert unconditional

dominicm 2018-05-19T22:09:16.000070Z

I'm worried about unconditional insert, because I don't want ordering to become a problem. The intermediate facts also feel "icky", I think because they expose a part of the LHS which isn't able to match the user's view of the world. It feels more incidental, and less domain.

2018-05-19T22:41:04.000035Z

I like to be able to avoid unconditional inserts. But there are reasons where it can’t be easily avoided currently. Those are mostly around expressing removing old facts etc. I typically don’t use it though.

2018-05-19T22:41:18.000108Z

I don’t see intermediate facts as a bad thing. I think it is really common.

2018-05-19T22:41:55.000062Z

Often have to express intermediate concepts to connect rules for more complex logical conditions. At least in my experience with the rules I’ve needed to write.