Fork me on GitHub

I have some questions about the fact-expr grammar over here:


Actually, looking at the schema I see that FactCondition :type is s/Any, bummer.


@cfleming Yeah, I can see where that is difficult and yes the “fact type” being anything makes things complicated


I’m pretty sure you can break Clara parsing if you try to use a fact type that seems too much like something else.


One thing that is interesting and probably should be part of the spec (I don’t believe it is now), is that variable bindings should always start with “?”


So in the case of the fact binding, it is the ::variable-binding from that PR


And perhaps we should just list a few things that a fact type should not be, like it shouldn’t be a symbol that starts with a “?”


I think it may not be ok for it to be a vector either. I seem to recall a bad parse example from long back where a fact type as a vector would mess up things.


Are there suggested patterns for rules that can require potentially-expensive lookups? If I have a rule that depends on content that could be retrieved from an API call / database hit / etc., is there a way to trigger that retrieval (and insert any facts it results in) only when the rule's other conditions are satisfied?


@tcarls that’s funny you bring that up since this topic came up fairly recently here


In short: I think in the future Clara could do better to avoid doing work when required previous conditions aren’t yet satisfied.


However, there is a workaround pattern:


;; Say you have this:
(defrule original
  [A (= ?id id)]
  [B (= ?id id) (do-expensive-thing x)]
  (insert (->C)))

It can be transformed to this:
(defrule part-1
  [A (= ?id id)]
  [?b <- B (= ?id id)]
  (insert (->MatchedB ?b)))

(defrule part-2
  [MatchedB (do-expensive-thing x)]
  (insert (->C)))


If you are in a situation where there may be some thrash of insert/retracts of A and B (from example) due to the truth maintenance of the network, then you can also consider adding either :salience or setup “activation groups” for rules like part-2. However, I’d only do that if there is actually a situation where it could be an issue.


Thank you -- that's useful advice.


Some details on salience and activations groups is written here: If you end up needing it. However, like I said, avoid it if unnecessary. It is additional complexity to deal with.


Is there a way to establish a conditional relationship between facts outside of a rule RHS? The case I'm thinking of is something like an article app, where articles have comments. Selecting an article makes it "active", and also triggers a request to fetch comments from the server. When the async request completes, comments will be inserted. It would be slick if retracting the active article fact also automagically retracted the inserted comments, but since the response handler for the comments request executes outside of a rule context, I don't see an obvious way to enforce that logical connection.


You could write something fairly easily to "deactivate" them (by joining the comment fact to the article and inserting an ActiveComment or something) but that wouldnt retract the base comment fact which could lead to build up over time. I don't know of any way to do what you are talking about without an external handler atm


they would have to come in on the same data object into the session which doesnt match the timeline you describe