Data-oriented session generation
The most immediately user-friendly way to define Clara rules and queries is directly in code using the defrule and defquery macros. These are intended to be human-readable syntax and are a quick way to start. Thus one can have usage patterns like the following:
(ns rule-ns)
(defrule cold-rule
[Temperature (= ?temperature temperature)(< temperature -20)]
=>
(insert! (->Cold ?temperature)))
(def session (mk-session 'rule-ns))
(def session-2 (mk-session [cold-rule]))
The two sessions above (session and session-2) are equivalent.
In addition to this DSL, Clara also has a data model for rules and queries, and this data can be passed in directly to mk-session without use of the DSL. For example:
(def session-3 (mk-session [(quote {:ns-name rule-ns,
:lhs [{:type clara.rules.testfacts.Temperature,
:constraints [(= ?temperature temperature) (< temperature -20)]}],
:rhs (do (insert! (->Cold ?temperature))),
:name "rule-ns/cold-rule"})]))
This will yield a session that is equivalent to those above. In fact, the variable cold-rule holds this data structure, which is why the definition form in session-2 works. This allows usage patterns such as the dynamic creation of rules and using Clara as a compiler target. For example, a specialized DSL could present a more constrained set of options than Clara’s and then compile to Clara rule forms in order to use the latter’s execution engine.