My basic problem is that I have a number of situations I would describe as "if some situation holds, insert this fact once and only once". I am unable to find a way to do this. Will post another comment with more discussion.
@dave.tenny uploaded a file: https://clojurians.slack.com/files/U7SGKB4LF/FB09PCNBX/discussion_of_prior_snippet.txt
So thanks to all for the help so far, but unless I can solve this "if some fact insert this other fact ONCE" problem I'm about ready to throw in the towel. It's really like I want each rule firing to be sensitive to the prior rule firings in a single call to (fire-rules), but that isn't what happens.
you absoultely are fighting the engine if you do an insert-unconditional based on an inference, but still want logical retractions. Why are you using unconditional again? i havent followed all the conversations.
that's just one way to do it, but it wouldn't work because that rule is going to fire twice and both firings will NOT see the Derived asserted by the first firing
So it's not even about truth maintenance so much as WHEN the LHS is evaluated
oh..hmm
I'm open to any reasonable way to do it, but given LHS matching those two facts I inserted, the result needs to be ONE derived.
I guess i dont understand why you need it only inserted once and not that the final state is one in the session.
because you are going to absolutely end up with two if you are using unconditional
@dave.tenny Introduce an intermediate type that can be duplicated. De-duplicate it, aka “merge” duplicates, in a separate rule. All rules downstream of the merge won’t know the difference.
Maybe all I need to do is replace the [Fact (= ?ftype ftype)] with use of an accumulator and predicate to express the "if there is some", and fire the rule once, haven't tried that
Can you give a sample of the merge logic?
Oops, I see you did, I think
the rules don’t assume what a “duplicate” means to you or what you want to do with them. You need an extra rule to configure that yourself.
Example, Maybe you wanted to know how many duplicates you had
you could then have (defrecord Derived [ftype matches-count])
Then
(defrule merge-derived
[?all <- (acc/all) :from [::derived-intermediate (= ?ftype (-> this :derived :ftype))]]
=>
;; Merging to one, but include the count of the "duplicates" for whatever reason
(insert! (-> ?all first :derived (assoc :matches-count (count ?all))))
ok, digesting this, back to drawing board
@dave.tenny Yep, I don’t see a reason for it there
I didn’t use it in the merge-derived
rule either
That use of with-meta
and :type
is interesting to know about when doing type
based dispatches.
Interesting tip
Anbody got an emacs cider clojure mode switch to adjust LHS condition indentation? My clauses don't seem to want to indent to the level of the prior clause.
Rather, bindings/predicates, not the clauses.
I don’t have special indentation rules
it indents less than ideal for vectors I’d say
I’ve mostly just let it happen
@dave.tenny I agree it isn’t ideal
for multiline, I typically go with:
[WorkerViableJob
(= ?user-id user-id)
(= ?job-type job-type)]
Clojure in general I find it helps to just give up on making lines short
Most rules I’ve written have positional syntax so everything on one line works well…joins typically line up nicely. In Clara I’d probably do the same for the same reason…try to group things vertically by joins