clara

http://www.clara-rules.org/
dominicm 2018-05-18T07:47:58.000046Z

http://www.clara-rules.org/docs/fact_type_customization/ Is it possible to set a fact type in such a way that this isn't needed?

dominicm 2018-05-18T07:52:45.000512Z

That might not be my problem actually. But when my type-fn is :a I get an error about alpha nodes if I try and refer to e.

2018-05-18T10:13:12.000216Z

@dominicm Could you give a minimal failing example? That doesn’t sound like something that should happen but we might be thinking about different things.

2018-05-18T13:11:14.000025Z

@dominicm I don’t see any context in your question. Did you post an example? You said where “this isn’t needed”, what were you referring to?

2018-05-18T13:14:51.000350Z

FYI I posted an example snippet overriding the fact type for something like tuples above. Well I put them in maps for key access by name.

2018-05-18T13:16:53.000227Z

You can’t refer to bare symbols that “represent” lookup keys in a rule condition if you are asking that though with regard to “referring to e. Clara currently only offers special syntactic access directly to record or “Java bean” field/accessors. If you are using generic types it doesn’t attempt to resolve like the symbol e to (:e this) This may be what you’re asking

2018-05-18T13:17:17.000219Z

It’d actually be interesting to explore making Clara offer that sort of syntax though on more generic data.

dominicm 2018-05-18T14:02:00.000660Z

Sorry. I got distracted when I got in and forgot to post it. On phone again, once I'm at the keyboard I will do it.

sveri 2018-05-18T14:57:11.000813Z

Hi, can someone point me to some literature on how to write my own rules engine? I have trouble finding usefull stuff.

zylox 2018-05-18T15:00:39.000832Z

clara is heavily based on this paper if you really want to write your own "engine" http://reports-archive.adm.cs.cmu.edu/anon/1995/CMU-CS-95-113.pdf

👍 1
sveri 2018-05-18T15:01:00.000922Z

I am just curious, thank you @zylox

2018-05-18T15:01:47.000774Z

Caveat: that paper is really old. There are many modern day rete extensions that Clara uses too. The paper is really good at explaining the foundations of rete though.

zylox 2018-05-18T15:01:56.000149Z

also just about any info you can get on rete will be intersting

2018-05-18T15:02:24.000291Z

The Drools/Jboss people also had some good blogs out there regarding rete.

2018-05-18T15:03:35.000053Z

Then there is also this great blog about Clara/rete here http://www.metasimple.org/2017/02/28/clarifying-rules-engines.html (I wrote it 😛 )

sveri 2018-05-18T15:05:01.000409Z

@mikerod thank to you too

dominicm 2018-05-18T15:07:24.000431Z

(ns roll-alt
  (:require
    [clara.rules :refer :all]
    [clara.tools.fact-graph :as fg]
    [clara.rules.accumulators :as accum]
    [rhizome.viz :as rhizome]))

(defrecord D [e a v])

(defrule todos-done-invisible
  ;; [:todo/title (= ?e e)]
  [:todo/done (= (:v this) false) (= ?e (:e this))]
  =>
  (insert!
    (->D ?e :todo/visible true)))

(comment
  (-> (mk-session
        :fact-type-fn :a
        :ancestors-fn (constantly [:all]))
      (insert
        (->D "foo" :todo/title "FOO!")
        (->D "foo" :todo/title "FOOBAR!")
        (->D "foo" :todo/done true)
        (->D "blah" :todo/done false))
      (fire-rules)
      (query visible-datoms)))
@mikerod the first line in the defrule doesn't work.

2018-05-18T15:16:09.000414Z

@dominicm that seems related to the explanation I at least attempted to give above about when you can refer to “field name” symbols directly in a rule

2018-05-18T15:16:35.000798Z

Clara compiler cannot statically/compile time know what those symbols mean since the rule condition has a custom type that can’t be introspected

2018-05-18T15:17:36.000829Z

It’d be interesting if Clara added support for you to explicitly state “fields” that go with custom fact types. But nothing like that right now. You’d have to do (:e this) instead of e or use destructuring as you have in the past

2018-05-18T15:20:26.000023Z

When rules have records or other types of classes directly in the rule condition Clara compiler will reflect on the class to determine its available field names. When it can do that, you can refer to field names directly as their name symbol.

dominicm 2018-05-18T15:29:49.000730Z

> Clara compiler cannot statically/compile time know what those symbols mean since the rule condition has a custom type that can’t be introspected That explains it to me, that's entirely what I was missing. It obviously worked when I wrote the form this way:

(defrule todos-done-invisible
  [?d <- D (= a :todo/title)]
  =>
  (insert!
    (->D (:e ?d) :todo/visible true)))
Which has a trade-off.

dominicm 2018-05-18T15:30:21.000853Z

I was a bit confused because it was still a record, ergo it should work (in my head).

dominicm 2018-05-18T15:30:47.000785Z

I looked for something to provide a custom keys function, and when I didn't find it, I presumed I was missing something.

2018-05-18T15:45:00.000648Z

@dominicm It’d be interesting to have a fn that takes your custom “type” and returns a set of “field keys”

2018-05-18T15:45:13.000323Z

and that’d be caleld when the compiler was compiling rules and then it’d allow for the shorter accessors

2018-05-18T15:45:43.000721Z

Yeah, Clara just has built-in special casing to class types since they have reflection utilities available to find out how to resolve those symbols

2018-05-18T15:46:11.000258Z

I’ll add that you probably don’t want to write all your rules against a single type like D, so that isn’t a pattern I’d advocate

1
2018-05-18T15:46:34.000810Z

It’d lead to a lot of thrash in the rules since every insert/retract would potentially affect every rule

2018-05-18T15:46:52.000549Z

The fact type serves as, what I’d call, the first level of discrimination/partitioning in the network.

dominicm 2018-05-18T16:14:13.000570Z

My data set isn't particularly large I think. I'm struggling to come up with good fact types for my domain. But that's likely a thing on my side.

dominicm 2018-05-18T16:35:50.000788Z

The problem I have is that I'm operating in a large domain, and I'm asserting facts on a per-key level, instead of whole entities.

dominicm 2018-05-18T16:36:54.000435Z

I suppose I could generate something like S3BucketFact which takes an id, key and value. But it's not so different from my datom record.

2018-05-21T09:41:53.000428Z

Haven’t read through all this, but FYI the ancestors-fn sounds like it could help you as well. So you could have rules matching all S3BucketFact as well as more rules matching only “subtypes” of S3BucketFact

2018-05-21T09:42:05.000177Z

@dominicm

dominicm 2018-05-21T09:44:17.000124Z

Yeah, I'm deriving all my records, so that I can do a query for all "Props"

dominicm 2018-05-21T09:44:41.000306Z

I've introduced a meta "Resource" which goes into the "e" slot too, to make it easier to query for resources without getting the duplicates from props.

dominicm 2018-05-18T16:47:42.000384Z

Or should I be creating records at the level of S3BucketName, s3bucketYYY, etc.?

2018-05-18T17:19:50.000039Z

don’t know about that

2018-05-18T17:20:06.000302Z

maybe the “fact type” should be the “attribute” slot of these sorts of facts? I’m not sure

dominicm 2018-05-18T17:59:57.000049Z

I guess I can invent static generation of that somehow later. It feels less "open".

2018-05-18T18:43:46.000402Z

@dominicm I think it’d come down to the sort of rules you were needing to write

2018-05-18T18:44:19.000410Z

the fact type is just a useful way to group facts across the network that are coming from an external and also to categorize derived data

2018-05-18T18:45:30.000713Z

I don’t see the fact types as being a closed off concept. They are just what the rules refer to to match things, join things, and check other constraints. All of this is probably too vague though. I don’t have a good enough understand of what your data might be looking like and the sorts of things you want to do with it.

2018-05-18T18:45:57.000342Z

This now does make me wonder what sort of “fact type”s are used in #precept

dominicm 2018-05-18T18:52:11.000625Z

I've been thinking the same, and also how certain problems of querying are solved, particularly around duplicate entities, potentially. There must be a few additional aspects to the querying in precept over what Clara provides alone.

dominicm 2018-05-18T18:55:51.000231Z

It was interesting to see several rules disappear when I got rid of the D record in favour of XFact records. I'm interested to see what happens with X-Y records.

dominicm 2018-05-18T19:36:35.000060Z

Without having at least the concept of "S3Bucket" and "S3BucketFact" it's quite difficult to do "All S3 buckets must have :foo 2", because the ?e is duplicated across so many facts. I could perhaps use an accumulator, but it seems more natural to have strict types.

dominicm 2018-05-18T20:19:13.000025Z

I've written a macro which is run like (defType Box) will generate: - (defrecord Box) - (defrecord BoxFact) - (derive Box ::Type) (derive BoxFact ::Fact) - Function for converting to Box from other types - Function for "scoping" a series of [a v] into Facts. I'm moving rather fast. I haven't gone really deep yet, but I'm going to see how far I can get without declaring every possible attribute on a Box as a type.

dominicm 2018-05-18T20:22:14.000372Z

It's certainly cool to see the addition of a route to an app cause the subnet to change, and the route53 records & load balancers to be created.

👍 1
dominicm 2018-05-18T22:15:40.000082Z

Sorry, I'm tripping over things I don't understand again,

(defquery created-by
  [:?for]
  [?fact <- ::Fact
   (= ?by (:e this))
   (= (:a this) :roll/created-for)
   (= (:v this) ?for)])
I'm getting back a result where :?for is different to what I input as a parameter: (query s created-by :?for (->Box "app" nil)). I don't really understand why, any advice?

2018-05-18T22:54:56.000096Z

the query returns all 3 bound variables and 1 match as expected

2018-05-18T22:55:09.000041Z

if I tweak the query or the inserted ::Fact, the results go away as expected too