This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-08-08
Channels
- # architecture (8)
- # beginners (78)
- # boot (20)
- # cider (81)
- # clara (53)
- # cljdoc (10)
- # cljsjs (3)
- # clojure (55)
- # clojure-boston (1)
- # clojure-dev (25)
- # clojure-nl (3)
- # clojure-uk (65)
- # clojurescript (65)
- # core-async (1)
- # cursive (41)
- # data-science (4)
- # datomic (16)
- # editors (74)
- # emacs (17)
- # events (1)
- # figwheel (3)
- # hyperfiddle (39)
- # immutant (16)
- # jobs-discuss (62)
- # juxt (2)
- # keechma (2)
- # leiningen (6)
- # mount (7)
- # nrepl (1)
- # off-topic (30)
- # onyx (14)
- # protorepl (2)
- # re-frame (4)
- # reagent (15)
- # reitit (19)
- # shadow-cljs (102)
- # sim-testing (1)
- # spacemacs (44)
- # specter (15)
- # tools-deps (50)
- # vim (2)
@mikerod Do you know if there is a way to go from Java -> Clojure when rules are keywords and not records/java beans?
I have a Clara rulebase that, for comprehensibility reasons, I’d like to split into “phases.” So, phase 1 gets a bunch of facts, the rules fire, and new facts are generated. Somehow, this becomes the input to phase 2, which fires a new set of rules, generating new facts. Etc. I’m not sure what the best way is to pass the output of one phase into the next. Originally I was thinking I’d just take the session from phase 1 and use that as the starting point for phase 2. But unless I’m missing something, it’s not possible to load new rules into an extant session. So I guess what I need to do is to just grab all the “output” facts out of phase 1 and insert them into a new session for phase 2. Is there a simpler way to do this than by writing (and then executing) a query for each and every fact type?
@enn > So I guess what I need to do is to just grab all the “output” facts out of phase 1 and insert them into a new session for phase 2. Is there a simpler way to do this than by writing (and then executing) a query for each and every fact type? I think this is likely a smoother approach (there is an alternative I can mention in a min) As far as worrying about querying for too many types, maybe you can make a “parent” type for the output types you care about and just have a query on that parent type.
Another possibility is to just use one session with all the rules. I’m not sure what about your logic makes it where you’d want some rules to be separate from others. Are you worried about them running too early or something, performance?, etc
I don’t understand your situation enough, but there is something called “activation groups” that can also be considered in some cases that may relate to yours https://github.com/cerner/clara-rules/blob/0.18.0/src/main/clojure/clara/rules.cljc#L328-L331
No, they’re all in one session now and it works fine performance-wise. It’s more about making it easier for the programmer to understand the universe of rules and fact types in play at a given point in the code.
And making it easy to ensure that an intermediate fact type (used to derive some other final result) does not get inadvertently referenced outside of its intended scope
Maybe my whole idea is antithetical to the idea that a rules engine hides some of the order-of-execution concerns of regular code? I’m not sure.
there would be a slight cost of taking facts from queries of one session and inserting again into another session, but that may not really be a concern
and I’d also sort of argue that rules should be able to somewhat function in aggregation with one another
where they can all share related information when relevant, but they are also fine when the information they need isn’t present etc
> And making it easy to ensure that an intermediate fact type (used to derive some other final result) does not get inadvertently referenced outside of its intended scope I think this is the most interesting concern though.
If everything gets lumped together, I can see how it could become problematic if you were wanting to have a better control on scope
@jeremy642 I don’t think I understand the question. You want to use rules with “keyword” sort of type dispatch, but on underlying Java objects? Maybe show a dummy example or something.
I have rules built on a keyword type dispatch. I wasn't sure if there might be a way to create them from Java.
More a question on Java -> Clojure interop I guess than clara-rules. How I might go about creating the necessary type map for clara-rules from Java.
@jeremy642 you can provide a custom fact-type-fn
(and ancestors-fn
if relevant) http://www.clara-rules.org/docs/fact_type_customization/
This may be what you are looking for. e.g. the fact-type-fn
could take an arbitrary (Java) object and map it to some keyword/alternative typing system you have within the rules
I’m not sure if you already have a custom fact-type-fn
or not though. You might since I see you have a map with :weather-fact-type
Clara’s default is clojure.core/type
, which is implemented as (or (get (meta x) :type) (class x))
Yeah I was just thinking of a way to take Java Maps and Convert it to Keyword Key Map in the fact-type-fn?
depending on what is priority, you may flip the if
above and do alternative things. I was just showing the idea of what could be done at least.
Currently the custom fact-type-fn looks for :type or something like that. I'll have to grab the work laptop. This just came to me off the top of my head.
so for the fact-type-fn
you just need to return the type (a keyword in your case I think)
but if you want to also work with the Java data as clj maps, like this: (< (:temperature this) 0)
, you’d have to convert the facts themselves coming into the session
the fact-type-fn
doesn’t transform the facts that are used during constraint matching. It just gives a value that is used as the “fact type” partitioning of the network
What I’ve done typically is to have some fairly basic rules to match those types and apply any sort of useful filtering if performance was a conern
(defrule find-java-things
[JavaThing (= x ?x)]
=>
(insert! {:fact-type :thing
:x ?x}))
I was thinking about keeping the rules in a seperate jar. And allowing Java applications and Clojure applications import and use the rules in that jar. The question was just how to define the facts when the rules were all in Clojure and no beans were provided that allowed Java to create them.
(defrule find-java-things
[?j <- JavaThing (= x ?x)]
=>
(insert! (with-meta {:fact-type :thing
:x ?x}
{:source ?j})))
If it’s a classpath issue, where you won’t know the types ahead of time you’ll have to be more tricky
and you have to write a separate ruleset that does know about specific type mapping parts - or maybe you don’t need rules for that transformation layer at all.
I thought about just writing a interface for Java to call and create facts, insert into engine. But the rule engine itself would most likely need to be run in clojure and not instantiated from Java so it's pretty self contained. It'd save me the hassle of dealing with java vs clojure types.