Writing Rules

Most users write rules with defrule, which uses this structure:

defrule railroad diagram

Here’s a simple example:

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

Hopefully this seems pretty intuitive, but let’s take a closer look at the pieces. We start with:

(defrule free-lunch-with-gizmo
"Anyone who purchases a gizmo gets a free lunch."

These just declare the rule name and include an optional documentation string. Next we have the rule’s left-hand side, which is everything before the => symbol:

  [Purchase (= item :gizmo)]

The left-hand side holds the conditions needed for the rule to fire. In this case we just check if there is a Purchase record (in this case a Clojure record or Java Bean) with an item that is a gizmo.

Now we look at the right-hand side of the rule, everything after the => symbol:

(insert! (->Promotion :free-lunch-with-gizmo :lunch)))

This is just a Clojure expression! It can call arbitrary functions or even have side effects. In this case the expression is insert a new fact into the working memory, that there is a free lunch promotion here.

Here’s one that is a bit more sophisticated:

(defrule grant-discount-months  
[Purchase (= ?month (get-month date))]
[DiscountMonth (= ?month month)]
=>
(insert! (->GrantDiscount :for-month ?month)))

Here we demonstrate variable binding and unification between rule conditions. This calls some get-month function and binds it to a ?month variable, and the rule will only be satisfied if there is is a discount that matches the month. Details on this are in the Writing Expressions documentation.

What’s next?