Skip to content
Ryan Brush edited this page Sep 14, 2013 · 28 revisions

Developer documentation is in progress.

Defining rules

Rules are typically defined with defrule, which has this structure:

defrule railroad diagram

A simple rule looks like this:

(defrule free-lunch-with-gizmo
  "Anyone who purchases a gizmo gets a free lunch."
  [Purchase (= item :gizmo)]
  =>
  (insert! (->Promotion :free-lunch-with-gizmo :lunch)))

Where Purchase is a Clojure Record or Java JavaBean containing an item field. If there exists a purchase that matches the :gizmo keyword, a new promotion is inserted into working memory, by simply creating a new Promotion record.

The left-hand side of the rule -- everything prior to the "=>" in the above -- uses a constraint expression described in the Constraint Expressions section below.

The right-hand side of the rule -- everything past the "=>" in the above example -- is simply a Clojure S-expression and can invoke arbitrary code, or use insert! to insert new information into the working memory.

Defining queries

Queries are typically defined with defquery, which has the following structure:

defquery railroad diagram

A sample query looks like this:

(defquery get-promotions
  "Query to find promotions for the purchase."
  []
  [?promotion <- Promotion])

The first argument is a vector of keywords to indicate parameters to a query. For instance, if we wanted to run a query that retrieves only a certain type of promotions, we might write this:

(defquery get-promotions
  "Query to find promotions for the purchase."
  [:?type]
  [?promotion <- Promotion (== ?type type)]) ; Bind the ?type query to the promotion type.

A caller may then execute that query with arguments. So if we only wanted to find lunch promotions, we might perform the query like this:

(query session get-promotions :?type :lunch)

The conditions used by a query are the same structure as the left-hand side of a rule. See the Condition Expressions section below for usage.

Condition Expressions

Condition Expressions are the contents of the left-hand side of rules, or the constraints used in queries.

This part of rules and queries contains a series of expressions, each of which is one of the following:

  • A fact expression, which selects a fact based on some given criteria.
  • A boolean expression, which is simply a hierarchical and/or/not structure of other expressions.
  • An accumulator, which is mechanism to reason about collections of facts
  • A test, which is an arbitrary Clojure S-expression that can run predicate-style tests on variables bound earlier in the rule or query.

Details on each of these are below.

Variable Bindings

One ke

Fact Expressions

fact expression

Fact expressions are the simplest and most common form of Clara conditions. They start with an optional binding for the fact, in the form of [?variableName <- MyFactType]. The fact type is then followed by zero or more S-expressions which can either be predicates run against a fact, or bindings (via the == macro), as described above.

A simple fact expression may look like this:

[?person <- Person (= first-name "Alice") (== ?last-name last-name)]

This example does the following:

  • Matches all facts of type Person
  • Eliminates any Person facts that don't have a first-name attribute that is equal to "Alice"
  • Creates a new binding ?last-name, which contains the value of the last-name field in matched Person facts.
  • Creates a new binding ?person, which contains the value of the matched Person object.

Boolean Expressions

boolean expression

TODO: add details.

Accumulators

accumulator expression

TODO: add details

Tests

test expression

TODO: add details

Additional Resources

Railroad diagrams generated with http://railroad.my28msec.com/rr/ui

Clone this wiki locally