3.1.2 Forward Chaining Syntax

Forward chaining rule bodies are defined by:

<body> ::=
          [:context <context-name>]
          [:priority <priority-number>]
          <forward-condition>* --> <expression>*)

where <context-name> is the name of a context which has already been defined (see Control Flow) defaulting to default-context , and <priority-number> is a number (see Control Flow) defaulting to 10 .

The syntax for forward-conditions is :

<forward-condition> ::=
    (<class-name> <variable> [<slot-name> <term>]*)
     |  (test <lisp-expr>)
     |  (not <forward-condition>+)
     |  (logical <forward-condition>+)

(<class-name> <variable> [<slot-name> <term>]*) is an object-base match where the variables (introduced by "?") in <term> are bound (via destructuring) to the corresponding data in the slot named by <slot-name>. <variable> is a single variable bound to the object matched.

Note: "?" on its own denotes an anonymous variable which always matches.

(test <lisp-expr>) is a Lisp test where <lisp-expr> is any Lisp expression using the variables bound by other conditions, and which must succeed (return non- nil ) for the condition to match. Computationally cheap Lisp tests can frequently be used to reduce the search space created by the object base conditions. Lisp tests, and any functions invoked by them, should not depend on any dynamic global data structures, as changing such structures (and hence the instantiations of the rule) will be invisible to the inference engine.

(not <forward-condition>+) is simply a negated condition. A negated condition never binds any variables outside its scope. Variables not bound before the negation will remain unbound after it.

(logical <forward-condition>+) is used to indicate clauses that describe the logical dependencies amongst objects. The enclosed conditions are matched against the object base as normal, but if the rule fires and creates new objects (by assert or make-instance ) then these objects are associated with the enclosed conditions. If the conditions are found to be false in the future, then the created objects are erased automatically (see erase below). There can be at most one logical clause in a rule (though it can contain multiple subclauses) and it must be the first clause in the rule.

Note that if a forward chaining rule contains any conditions at all then it must contain at least one object base reference of the form

(<class-name> <variable> ...)

The syntax for expressions is:

<expression> ::=
         |(erase <variable>)
         |(assert (<class-name> <variable> 
                   [<slot-name> <term>]*))
         |(context <context-list>)
         |(<lisp-expr> <term>*)

<forward-condition> is a forward condition which must succeed for execution of the action part of the rule to continue.

(erase <variable>) removes the instance bound to <variable> from the knowledge base. It is an error if <variable> is bound to anything but a KnowledgeWorks instance.

(assert (<class-name> <variable> [<slot-name> <term>]*)) is an assertion which modifies the contents of the object base, where if <variable> is unbound a new object of the given class with the given slot-values is created, and if it is bound, the object to which it is bound has its slots modified to the given values.

(context <context-list>) adds the given list of contexts to the top of agenda (see Control Flow).

(return) passes control to the top context on the agenda and removes it from the agenda (see Control Flow).

(<lisp-expr> <term>*) binds the result or results of calling <lisp-expr> to the <term> s with execution of the rule terminating if any bindings fail (if no <term> s are given execution will always continue).

<goal> may be any backward chaining goal expression (see Backward Chaining).

Note that in the action part of a rule, only backward chaining goals and object base matches invoke the backward chainer. Example

KnowledgeWorks and Prolog User Guide - 4 Apr 2005