Writing Rules
Most users write rules with defrule, which uses this structure:
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?
- See the Writing Expressions section for details on writing expressions for a rule’s left-hand side.
- See the Writing Queries section for how to query a rule session.