17. Jess Constructs
A construct is something that looks like a function, but isn't one. It generally has odd syntax that can't be used in a regular function call. Most of the names starting with "def-" in Jess are construct names: defrule, defglobal, etc. You can only use constructs at the top level of a Jess program -- i.e., you can't use a construct on the right hand side of a rule, or inside a function.
A construct is basically the same as a special form in Lisp or Scheme. The odd syntax has to be handled specially by the parser, hence the name.
17.1. deffacts
- Syntax:
-
(deffacts deffacts-name ["Documentation comment"] (fact)* )
- Description:
- A deffacts is just a list of facts. When the "reset" function is called, Jess clears working memory, asserts the special "initial-fact" fact, and then asserts all the facts defined by deffacts.
17.2. deffunction
- Syntax:
-
(deffunction function-name (argument*) ["Documentation comment"] (function call)* )
- Description:
- A deffunction is a function written in the Jess language. You can call deffunctions from the Jess prompt, from a rule, or from another deffunction.
17.3. defglobal
- Syntax:
-
(defglobal ?*name = value [?*name = value]* )
- Description:
- A defglobal construct defines one or more global variables and sets their initial values. The name of a global variable must begin and and with an asterisk (*).
17.4. defmodule
- Syntax:
- (defmodule module-name ["Documentation comment"] )
- Description:
- The defmodule construct introduces a Jess module. The current module is set to be the new module, so any rules defined after a defmodule will implicitly belong to that module.
17.5. defquery
- Syntax:
-
(defquery query-name ["Documentation comment"] [(declare (variables variable+) (node-index-hash value) (max-background-rules value))] (conditional element)* )
- Description:
- A query consists of an optional variable declaration followed by a list of conditional elements. A conditional element is either a pattern, or a grouping construct like "and", "or", or "not." Queries are used to search working memory for facts that satisfy the conditional elements. A query can be invoked using the "run-query*" function.
17.6. defrule
- Syntax:
-
(defrule rule-name ["Documentation comment"] [(declare (salience value) (node-index-hash value) (auto-focus TRUE | FALSE) (no-loop TRUE | FALSE))] (conditional element)* => (function call)* )
- Description:
- A rule consists of a left-hand side, the symbol "=>", and a right-hand side, in that order. The left-hand side is made up of zero or more conditional elements, while the right-hand side consists of zero or more function calls. A conditional element is either a pattern, or a grouping construct like "and", "or", or "not." The conditional elements are matched against Jess's working memory. When they all match, and if the engine is running, the code on the rule's right-hand side will be executed.
17.7. deftemplate
- Syntax:
-
(deftemplate template-name [extends template-name] ["Documentation comment"] [(declare (slot-specific TRUE | FALSE) (backchain-reactive TRUE | FALSE) (from-class class name) (include-variables TRUE | FALSE) (ordered TRUE | FALSE))] (slot | multislot slot-name [(type ANY | INTEGER | FLOAT | NUMBER | SYMBOL | STRING | LEXEME | OBJECT | LONG)] [(default default value)] [(default-dynamic default value)])*)
- Description:
-
A deftemplate describes a kind of fact, precisely in the same way as a Java class describes a kind of object. In particular, a deftemplate lists the "member variables" (called slots) that this particular kind of fact can have.
Deftemplate definitions can include a "declare" section. Each declaration will affect either how the template is defined or how facts that use the template will behave.
The first declaration we'll learn about is slot-specific. A template with this declaration will be matched in a special way: if a fact, created from such a template, which matches the left-hand-side of a rule is modified, the result depends on whether the modified slot is named in the pattern used to match the fact. As an example, consider the following:
Jess> (deftemplate D (declare (slot-specific TRUE)) (slot A) (slot B)) (defrule R ?d <- (D (A 1)) => (modify ?d (B 3)))
Without the "slot-specific" declaration, this rule would enter an endless loop, because it modifies a fact matched on the LHS in such a way that the modified fact will still match. With the declaration, it can simply fire once. This behavior is actually what many new users expect as the default, so the slot-specific declaration probably ought to be used most of the time.
By default, only JavaBeans properties generate slots. But if you include the optional (include-variables TRUE) declaration in your template, then Jess will also create slots corresponding to the public instance variables of the class.
Other declarations are described in this chapter.