Table of ContentsCLIPS BPG
Basic Programming Guide
Version 6.xx January 2010
CLIPS DocumentationTwo documents are provided with CLIPS. The CLIPS Reference Manual which is split into the following parts:
AcknowledgementsAs with any large project, CLIPS is the result of the efforts of numerous people. The primary contributors have been: Robert Savely, who conceived the project and provided overall direction and support; Chris Culbert, who managed the project and wrote the original CLIPS Reference Manual; Gary Riley, who designed and developed the rule based portion of CLIPS, co authored the CLIPS Reference Manual, and developed the Macintosh interface for CLIPS; Brian Donnell, who designed and developed the CLIPS Object Oriented Language (COOL) and co authored the CLIPS Reference Manual; Bebe Ly, who developed the X Window interface for CLIPS; Chris Ortiz, who developed the original Windows 95 interface for CLIPS; Dr. Joseph Giarratano of the University of Houston-Clear Lake, who wrote the CLIPS User’s Guide; and Frank Lopez, who designed and developed CLIPS version 1.0 and wrote the CLIPS 1.0 User’s Guide.
Section 1 IntroductionThis manual is the Basic Programming Guide for CLIPS. It is intended for users interested in the syntax of CLIPS. No previous expert system background is required, although a general understanding of computer languages is assumed. Section 2 of this manual provides an overview of the CLIPS language and basic terminology. Sections 3 through 11 provide additional details regarding the CLIPS programming language on topics such as rules and the CLIPS Object Oriented Programming Language (COOL). The types of actions and functions provided by CLIPS are defined in section 12. Finally, commands typically used from the CLIPS interactive interface are described in section 13.
Section 2 CLIPS OverviewThis section gives a general overview of CLIPS and of the basic concepts used throughout this manual. 2.1 Interacting with CLIPSCLIPS expert systems may be executed in three ways: interactively using a simple, text oriented, command prompt interface; interactively using a window/menu/mouse interface on certain machines; or as embedded expert systems in which the user provides a main program and controls execution of the expert system. Embedded applications are discussed in the Advanced Programming Guide. In addition, a series of commands can be automatically read directly from a file when CLIPS is first started or as the result of the batch command.
2.1.1 Top Level CommandsThe primary method for interacting with CLIPS in a non embedded environment is through the CLIPS command prompt (or top level). When the “CLIPS>” prompt is printed, a command may be entered for evaluation. Commands may be function calls, constructs, global variables, or constants. If a function call is entered (see section 2.3.2), that function is evaluated and its return value is printed. Function calls in CLIPS use a prefix notation—the operands to a function always appear after the function name. Entering a construct definition (see section 2.3.3) at the CLIPS prompt creates a new construct of the appropriate type. Entering a global variable (see section 2.4.3) causes the value of the global variable to be printed. Entering a constant (see section 2.3.1) at the top level causes the constant to be printed (which is not very useful). For example,
CLIPS> (+ 3 4) 7 CLIPS> (defglobal ?*x* = 3) CLIPS> ?*x* 3 CLIPS> red red CLIPS>
2.1.2 Automated Command Entry and LoadingSome operating systems allow additional arguments to be specified to a program when it begins execution. When the CLIPS executable is started under such an operating system, CLIPS can be made to automatically execute a series of commands read directly from a file or to load constructs from a file. The command line syntax for starting CLIPS and automatically reading commands or loading constructs from a file is as follows: Syntax clips <option>*
-f2 <filename> | -l <filename>
2.1.3 Integration with Other LanguagesWhen using an expert system, two kinds of integration are important: embedding CLIPS in other systems, and calling external functions from CLIPS. CLIPS was designed to allow both kinds of integration.
2.2 Reference Manual SyntaxThe terminology used throughout this manual to describe the CLIPS syntax is fairly common to computer reference manuals. Plain words or characters, particularly parentheses, are to be typed exactly as they appear. Bolded words or characters, however, represent a verbal description of what is to be entered. Sequences of words enclosed in single angle brackets (called terms or non terminal symbols), such as <string>, represent a single entity of the named class of items to be supplied by the user. A non terminal symbol followed by a *, represents zero or more entities of the named class of items which must be supplied by the user. A non terminal symbol followed by a +, represents one or more entities of the named class of items which must be supplied by the user. A * or + by itself is to be typed as it appears. Vertical and horizontal ellipsis (three dots arranged respectively vertically and horizontally) are also used between non terminal symbols to indicate the occurrence of one or more entities. A term enclosed within square brackets, such as [<comment>], is optional (i.e. it may or may not be included). Vertical bars indicate a choice between multiple terms. White spaces (tabs, spaces, carriage returns) are used by CLIPS only as delimiters between terms and are ignored otherwise (unless inside double quotes). The ::= symbol is used to indicate how a non terminal symbol can be replaced. For example, the following syntax description indicates that a <lexeme> can be replaced with either a <symbol> or a <string>.
2.3 Basic Programming ElementsCLIPS provides three basic elements for writing programs: primitive data types, functions for manipulating data, and constructs for adding to a knowledge base. 2.3.1 Data TypesCLIPS provides eight primitive data types for representing information. These types are float, integer, symbol, string, external address, fact address, instance name and instance address. Numeric information can be represented using floats and integers. Symbolic information can be represented using symbols and strings.
2.3.2 FunctionsA function in CLIPS is a piece of executable code identified by a specific name which returns a useful value or performs a useful side effect (such as displaying information). Throughout the CLIPS documentation, the word function is generally used to refer only to functions which return a value (whereas commands and actions are used to refer to functions which have a side effect but generally do not return a value).
(* 5 6.0 2) (+ 3 (* 8 9) 4) (* 8 (+ 3 (* 2 3 4) 9) (* 3 4))
2.3.3 ConstructsSeveral defining constructs appear in CLIPS: defmodule, defrule, deffacts, deftemplate, defglobal, deffunction, defclass, definstances, defmessage handler, defgeneric, and defmethod. All constructs in CLIPS are surrounded by parentheses. The construct opens with a left parenthesis and closes with a right parenthesis. Defining a construct differs from calling a function primarily in effect. Typically a function call leaves the CLIPS environment unchanged (with some notable exceptions such as resetting or clearing the environment or opening a file). Defining a construct, however, is explicitly intended to alter the CLIPS environment by adding to the CLIPS knowledge base. Unlike function calls, constructs never have a return value.
2.4 Data AbstractionThere are three primary formats for representing information in CLIPS: facts, objects and global variables. 2.4.1 FactsFacts are one of the basic high level forms for representing information in a CLIPS system. Each fact represents a piece of information which has been placed in the current list of facts, called the fact list. Facts are the fundamental unit of data used by rules (see section 2.5.1).
2.4.1.1 Ordered FactsOrdered facts consist of a symbol followed by a sequence of zero or more fields separated by spaces and delimited by an opening parenthesis on the left and a closing parenthesis on the right. The first field of an ordered fact specifies a “relation” that applied to the remaining fields in the ordered fact. For example, (father of jack bill) states that bill is the father of jack.
(altitude is 10000 feet) (grocery-list bread milk eggs)
2.4.1.2 Non ordered FactsOrdered facts encode information positionally. To access that information, a user must know not only what data is stored in a fact but which field contains the data. Non ordered (or deftemplate) facts provide the user with the ability to abstract the structure of a fact by assigning names to each field in the fact. The deftemplate construct (see section 3) is used to create a template which can then be used to access fields by name. The deftemplate construct is analogous to a record or structure definition in programming languages such as Pascal and C.
Some examples of deftemplate facts are shown following.
(point-mass (x-velocity 100) (y-velocity -200)) (class (teacher “Martha Jones”) (#-students 30) (Room “37A”)) (grocery-list (#-of-items 3) (items bread milk eggs))
(class (#-students 30) (teacher “Martha Jones”) (Room “37A”)) (class (Room “37A”) (#-students 30) (teacher “Martha Jones”))
(class 30 “Martha Jones” “37A”) (class “37A” 30 “Martha Jones”)
2.4.1.3 Initial FactsThe deffacts construct allows a set of a priori or initial knowledge to be specified as a collection of facts. When the CLIPS environment is reset (using the reset command) every fact specified within a deffacts construct in the CLIPS knowledge base is added to the fact list. 2.4.2 ObjectsAn object in CLIPS is defined to be a symbol, a string, a floating point or integer number, a multifield value, an external address or an instance of a user defined class. Section 2.3.1 explains how to reference instances of user defined classes. Objects are described in two basic parts: properties and behavior. A classis a template for common properties and behavior of objects which are instances of that class. Some examples of objects and their classes are:
2.4.2.1 Initial ObjectsThe definstances construct allows a set of a priori or initial knowledge to be specified as a collection of instances of user defined classes. When the CLIPS environment is reset (using the reset command) every instance specified within a definstances construct in the CLIPS knowledge base is added to the instance list. 2.4.3 Global VariablesThe defglobal construct allows variables to be defined which are global in scope throughout the CLIPS environment. That is, a global variable can be accessed anywhere in the CLIPS environment and retains its value independent of other constructs. In contrast, some constructs (such as defrule and deffunction) allow local variables to be defined within the definition of the construct. These local variables can be referred to within the construct, but have no meaning outside the construct. A CLIPS global variable is similar to global variables found in procedural programming languages such as LISP, C and Ada. Unlike C and Ada, however, CLIPS global variables are weakly typed (they are not restricted to holding a value of a single data type). 2.5 Knowledge RepresentationCLIPS provides heuristic and procedural paradigms for representing knowledge. These two paradigms are discussed in this section. Object oriented programming (which combines aspects of both data abstraction and procedural knowledge) is discussed in section 2.6. 2.5.1 Heuristic Knowledge – RulesOne of the primary methods of representing knowledge in CLIPS is a rule. Rules are used to represent heuristics, or “rules of thumb”, which specify a set of actions to be performed for a given situation. The developer of an expert system defines a set of rules which collectively work together to solve a problem. A rule is composed of an antecedent and a consequent. The antecedent of a rule is also referred to as the if portion or the left hand side (LHS) of the rule. The consequent of a rule is also referred to as the then portion or the right hand side (RHS) of the rule.
2.5.2 Procedural KnowledgeCLIPS also supports a procedural paradigm for representing knowledge like that of more conventional languages, such as Pascal and C. Deffunctions and generic functions allow the user to define new executable elements to CLIPS that perform a useful side effect or return a useful value. These new functions can be called just like the built in functions of CLIPS. Message handlers allow the user to define the behavior of objects by specifying their response to messages. Deffunctions, generic functions and message handlers are all procedural pieces of code specified by the user that CLIPS executes interpretively at the appropriate times. Defmodules allow a knowledge base to be partitioned. 2.5.2.1 DeffunctionsDeffunctions allow you to define new functions in CLIPS directly. In previous versions of CLIPS, the only way to have user defined functions was to write them in some external language, such as C or Ada, and then recompile and relink CLIPS with the new functions. The body of a deffunction is a series of expressions similar to the RHS of a rule that are executed in order by CLIPS when the deffunction is called. The return value of a deffunction is the value of the last expression evaluated within the deffunction. Calling a deffunction is identical to calling any other function in CLIPS. Deffunctions are covered comprehensively in Section 7. 2.5.2.2 Generic FunctionsGeneric functions are similar to deffunctions in that they can be used to define new procedural code directly in CLIPS, and they can be called like any other function. However, generic functions are much more powerful because they can be overloaded. A generic function will do different things depending on the types (or classes) and number of its arguments. Generic functions are comprised of multiple components called methods, where each method handles different cases of arguments for the generic function. For example, you might overload the “+” operator to do string concatenation when it is passed strings as arguments. However, the “+” operator will still perform arithmetic addition when passed numbers. There are two methods in this example: an explicit one for strings defined by the user and an implicit one which is the standard CLIPS arithmetic addition operator. The return value of a generic function is the evaluation of the last expression in the method executed. Generic functions are covered comprehensively in Section 8. 2.5.2.3 Object Message PassingObjects are described in two basic parts: properties and behavior. Object properties are specified in terms of slots obtained from the object’s class; slots are discussed in more detail in Section 2.4.2. Object behavior is specified in terms of procedural code called message handlers which are attached to the object’s class. Objects are manipulated via message passing. For example, to cause the Rolls Royce object, which is an instance of the class CAR, to start its engine, the user must call the send function to send the message “start engine” to the Rolls Royce. How the Rolls Royce responds to this message will be dictated by the execution of the message handlers for “start engine” attached to the CAR class and any of its superclasses. The result of a message is similar to a function call in CLIPS: a useful return value or side effect.
2.5.2.4 DefmodulesDefmodules allow a knowledge based to be partitioned. Every construct defined must be placed in a module. The programmer can explicitly control which constructs in a module are visible to other modules and which constructs from other modules are visible to a module. The visibility of facts and instances between modules can be controlled in a similar manner. Modules can also be used to control the flow of execution of rules. Defmodules are covered comprehensively in Section 10. 2.6 CLIPS Object Oriented LanguageThis section gives a brief overview of the programming elements of the CLIPS Object Oriented Language (COOL). COOL includes elements of data abstraction and knowledge representation. This section gives an overview of COOL as a whole, incorporating the elements of both concepts. Object references are discussed in Section 2.3.1, and the structure of objects is discussed in Sections 2.4.2 and 2.5.2.3. The comprehensive details of COOL are given in Section 9. 2.6.1 COOL Deviations from a Pure OOP ParadigmIn a pure OOP language, all programming elements are objects which can only be manipulated via messages. In CLIPS, the definition of an object is much more constrained: floating point and integer numbers, symbols, strings, multifield values, external addresses, fact addresses and instances of user defined classes. All objects may be manipulated with messages, except instances of user defined classes, which must be. For example, in a pure OOP system, to add two numbers together, you would send the message “add” to the first number object with the second number object as an argument. In CLIPS, you may simply call the “+” function with the two numbers as arguments, or you can define message handlers for the NUMBER class which allow you to do it in the purely OOP fashion.
2.6.2 Primary OOP FeaturesThere are five primary characteristics that an OOP system must possess: abstraction, encapsulation, inheritance, polymorphism and dynamic binding. An abstraction is a higher level, more intuitive representation for a complex concept. Encapsulation is the process whereby the implementation details of an object are masked by a well defined external interface. Classes may be described in terms of other classes by use of inheritance. Polymorphism is the ability of different objects to respond to the same message in a specialized manner. Dynamic binding is the ability to defer the selection of which specific message handlers will be called for a message until run time.
COOL allows the user to specify some or all of the properties and behavior of a class in terms of one or more unrelated superclasses. This process is called multiple inheritance. COOL uses the existing hierarchy of classes to establish a linear ordering called the class precedence list for a new class. Objects which are instances of this new class can inherit properties (slots) and behavior (message handlers) from each of the classes in the class precedence list. The word precedence implies that properties and behavior of a class first in the list override conflicting definitions of a class later in the list.
2.6.3 Instance set Queries and Distributed ActionsIn addition to the ability of rules to directly pattern match on objects, COOL provides a useful query system for determining, grouping and performing actions on sets of instances of user defined classes that meet user defined criteria. The query system allows you to associate instances that are either related or not. You can simply use the query system to determine if a particular association set exists, you can save the set for future reference, or you can iterate an action over the set. An example of the use of the query system might be to find the set of all pairs of boys and girls that have the same age. Section 3 Deftemplate ConstructOrdered facts encode information positionally. To access that information, a user must know not only what data is stored in a fact but which field contains the data. Non ordered (or deftemplate) facts provide the user with the ability to abstract the structure of a fact by assigning names to each field found within the fact. The deftemplate construct is used to create a template which can then be used by non ordered facts to access fields of the fact by name. The deftemplate construct is analogous to a record or structure definition in programming languages such as Pascal and C.
Syntax (deftemplate <deftemplate-name> [<comment>] <slot-definition>*)
<multislot-definition>
::= (slot <slot-name> <template-attribute>*)
::= (multislot <slot-name> <template-attribute>*)
<constraint-attribute>
::= (default ?DERIVE | ?NONE | <expression>*) | (default-dynamic <expression>*)
Example (deftemplate object (slot name) (slot location) (slot on-top-of) (slot weight) (multislot contents)) 3.1 Slot Default ValuesThe <default attribute> specifies the value to be used for unspecified slots of a template fact when an assert action is performed. One of two types of default selections can be chosen: default or dynamic default.
Example CLIPS> (clear) CLIPS> (deftemplate foo (slot w (default ?NONE)) (slot x (default ?DERIVE)) (slot y (default (gensym*))) (slot z (default-dynamic (gensym*)))) CLIPS> (assert (foo))
CLIPS> (assert (foo (w 3))) <Fact-0> CLIPS> (assert (foo (w 4))) <Fact-1> CLIPS> (facts) f-0 (foo (w 3) (x nil) (y gen1) (z gen2)) f-1 (foo (w 4) (x nil) (y gen1) (z gen3)) For a total of 2 facts. CLIPS> 3.2 Slot Default Constraints for Pattern MatchingSingle field slots that are not specified in a pattern on the LHS of a rule are defaulted to single field wildcards (?) and multifield slots are defaulted to multifield wildcards ($?). 3.3 Slot Value Constraint AttributesThe syntax and functionality of single and multifield constraint attributes are described in detail in Section 11. Static and dynamic constraint checking for deftemplates is supported. Static checking is performed when constructs or commands using deftemplates slots are being parsed (and the specific deftemplate associated with the construct or command can be immediately determined). Template patterns used on the LHS of a rule are also checked to determine if constraint conflicts exist among variables used in more that one slot. Errors for inappropriate values are immediately signaled. References to fact indexes made in commands such as modify and duplicate are considered to be ambiguous and are never checked using static checking. Static checking is enabled by default. This behavior can be changed using the set static constraint checking function. Dynamic checking is also supported. If dynamic checking is enabled, then new deftemplate facts have their values checked when added to the fact list. This dynamic checking is disabled by default. This behavior can be changed using the set dynamic constraint checking function. If an violation occurs when dynamic checking is being performed, then execution will be halted. Example (deftemplate object (slot name (type SYMBOL) (default ?DERIVE)) (slot location (type SYMBOL) (default ?DERIVE)) (slot on-top-of (type SYMBOL) (default floor)) (slot weight (allowed-values light heavy) (default light)) (multislot contents (type SYMBOL) (default ?DERIVE))) 3.4 Implied DeftemplatesAsserting or referring to an ordered fact (such as in a LHS pattern) creates an “implied” deftemplate with a single implied multifield slot. The implied multifield slot’s name is not printed when the fact is printed. The implied deftemplate can be manipulated and examined identically to any user defined deftemplate (although it has no pretty print form). Example CLIPS> (clear) CLIPS> (assert (foo 1 2 3)) <Fact-0> CLIPS> (defrule yak (bar 4 5 6) ⇒) CLIPS> (list-deftemplates) initial-fact foo bar For a total of 3 deftemplates. CLIPS> (facts) f-0 (foo 1 2 3) For a total of 1 fact. CLIPS> Section 4 Deffacts ConstructWith the deffacts construct, a list of facts can be defined which are automatically asserted whenever the reset command is performed. Facts asserted through deffacts may be retracted or pattern matched like any other fact. The initial fact list, including any defined deffacts, is always reconstructed after a reset command. Syntax
(deffacts <deffacts-name> [<comment>]
Example
(deffacts startup “Refrigerator Status” (refrigerator temp (get-temp)))
(initial-fact))
Section 5 Defrule ConstructOne of the primary methods of representing knowledge in CLIPS is a rule. A rule is a collection of conditions and the actions to be taken if the conditions are met. The developer of an expert system defines the rules which describe how to solve a problem. Rules execute (or fire) based on the existence or non existence of facts or instances of user defined classes. CLIPS provides the mechanism (the inference engine) which attempts to match the rules to the current state of the system (as represented by the fact list and instance list) and applies the actions.
5.1 Defining RulesRules are defined using the defrule construct. Syntax (defrule <rule-name> [<comment>] [<declaration>] ; Rule Properties
<conditional-element>* ; Left-Hand Side (LHS) Redefining a currently existing defrule causes the previous defrule with the same name to be removed even if the new definition has errors in it. The LHS is made up of a series of conditional elements (CEs) which typically consist of pattern conditional elements (or just simply patterns) to be matched against pattern entities. An implicit and conditional element always surrounds all the patterns on the LHS. The RHS contains a list of actions to be performed when the LHS of the rule is satisfied. In addition, the LHS of a rule may also contain declarations about the rule’s properties immediately following the rule’s name and comment (see section 5.4.10 for more details). The arrow (⇒) separates the LHS from the RHS. There is no limit to the number of conditional elements or actions a rule may have (other than the limitation placed by actual available memory). Actions are performed sequentially if, and only if, all conditional elements on the LHS are satisfied.
Example
(defrule example-rule “This is an example of a simple rule” 5.2 Basic Cycle Of Rule ExecutionOnce a knowledge base (in the form of rules) is built and the fact list and instance list is prepared, CLIPS is ready to execute rules. In a conventional language, the starting point, the stopping point, and the sequence of operations are defined explicitly by the programmer. With CLIPS, the program flow does not need to be defined quite so explicitly. The knowledge (rules) and the data (facts and instances) are separated, and the inference engine provided by CLIPS is used to apply the knowledge to the data. The basic execution cycle is as follows:
5.3 Conflict Resolution StrategiesThe agenda is the list of all rules which have their conditions satisfied (and have not yet been executed). Each module has its own agenda. The agenda acts similar to a stack (the top rule on the agenda is the first one to be executed). When a rule is newly activated, its placement on the agenda is based (in order) on the following factors:
5.3.1 Depth StrategyNewly activated rules are placed above all rules of the same salience. For example, given that fact a activates rule 1 and rule 2 and fact b activates rule 3 and rule 4, then if fact a is asserted before fact b, rule 3 and rule 4 will be above rule 1 and rule 2 on the agenda. However, the position of rule 1 relative to rule 2 and rule 3 relative to rule 4 will be arbitrary. 5.3.2 Breadth StrategyNewly activated rules are placed below all rules of the same salience. For example, given that fact a activates rule 1 and rule 2 and fact b activates rule 3 and rule 4, then if fact a is asserted before fact b, rule 1 and rule 2 will be above rule 3 and rule 4 on the agenda. However, the position of rule 1 relative to rule 2 and rule 3 relative to rule 4 will be arbitrary. 5.3.3 Simplicity StrategyAmong rules of the same salience, newly activated rules are placed above all activations of rules with equal or higher specificity. The specificity of a rule is determined by the number of comparisons that must be performed on the LHS of the rule. Each comparison to a constant or previously bound variable adds one to the specificity. Each function call made on the LHS of a rule as part of the :, =, or test conditional element adds one to the specificity. The boolean functions and, or, and not do not add to the specificity of a rule, but their arguments do. Function calls made within a function call do not add to the specificity of a rule. For example, the following rule
(item ?x ?y ?x) (test (and (numberp ?x) (> ?x (+ 10 ?y)) (< ?x 100))) ⇒)
5.3.4 Complexity StrategyAmong rules of the same salience, newly activated rules are placed above all activations of rules with equal or lower specificity. 5.3.5 LEX StrategyAmong rules of the same salience, newly activated rules are placed using the OPS5 strategy of the same name. First the recency of the pattern entities that activated the rule is used to determine where to place the activation. Every fact and instance is marked internally with a “time tag” to indicate its relative recency with respect to every other fact and instance in the system. The pattern entities associated with each rule activation are sorted in descending order for determining placement. An activation with a more recent pattern entities is placed before activations with less recent pattern entities. To determine the placement order of two activations, compare the sorted time tags of the two activations one by one starting with the largest time tags. The comparison should continue until one activation’s time tag is greater than the other activation’s corresponding time tag. The activation with the greater time tag is placed before the other activation on the agenda.
rule-5: f-1,f-2,f-3, rule-1: f-1,f-2,f-3 rule-2: f-3,f-1 rule-4: f-1,f-2, rule-3: f-2,f-1
rule-5: f-3,f-2,f-1, rule-1: f-3,f-2,f-1 rule-2: f-3,f-1 rule-4: f-2,f-1, rule-3: f-2,f-1 5.3.6 MEA StrategyAmong rules of the same salience, newly activated rules are placed using the OPS5 strategy of the same name. First the time tag of the pattern entity associated with the first pattern is used to determine where to place the activation. An activation thats first pattern’s time tag is greater than another activations first pattern’s time tag is placed before the other activation on the agenda. If both activations have the same time tag associated with the first pattern, then the LEX strategy is used to determine placement of the activation. Again, as with the CLIPS LEX strategy, negated patterns have pseudo time tags.
rule-3: f-2,f-1 rule-6: f-1,f-4 rule-5: f-1,f-2,f-3, rule-1: f-1,f-2,f-3 rule-4: f-1,f-2, 5.3.7 Random StrategyEach activation is assigned a random number which is used to determine its placement among activations of equal salience. This random number is preserved when the strategy is changed so that the same ordering is reproduced when the random strategy is selected again (among activations that were on the agenda when the strategy was originally changed). 5.4 LHS SyntaxThis section describes the syntax used on the LHS of a rule. The LHS of a CLIPS rule is made up of a series of conditional elements (CEs) that must be satisfied for the rule to be placed on the agenda. There are eight types of conditional elements: pattern CEs, test CEs, and CEs, or CEs, not CEs, exists CEs, forall CEs, and logical CEs. The pattern CE is the most basic and commonly used conditional element. Pattern CEs contain constraints which are used to determine if any pattern entities (facts or instances) satisfy the pattern. The test CE is used to evaluate expressions as part of the pattern matching process. The and CE is used to specify that an entire group of CEs must all be satisfied. The or CE is used to specify that only one of a group of CEs must be satisfied. The not CE is used to specify that a CE must not be satisfied. The exists CE is used to test for the occurence of at least one partial match for a set of CEs. The forall CE is used to test that a set of CEs is satisfied for every partial match of a specified CE. Finally, the logical CE allows assertions of facts and the creation of instances on the RHS of a rule to be logically dependent upon pattern entities matching patterns on the LHS of a rule (truth maintenance).
<conditional-element> ::= <pattern-CE> | <assigned-pattern-CE> | <not-CE> | <and-CE> | <or-CE> | <logical-CE> | <test-CE> | <exists-CE> | <forall-CE> 5.4.1 Pattern Conditional ElementPattern conditional elements consist of a collection of field constraints, wildcards, and variables which are used to constrain the set of facts or instances which match the pattern CE. A pattern CE is satisfied by each and every pattern entity that satisfies its constraints. Field constraints are a set of constraints that are used to test a single field or slot of a pattern entity. A field constraint may consist of only a single literal constraint:literal;, however, it may also consist of several constraints connected together. In addition to literal constraints, CLIPS provides three other types of constraints: connective constraints, predicate constraints, and return value constraints. Wildcards are used within pattern CEs to indicate that a single field or group of fields can be matched by anything. Variables are used to store the value of a field so that it can be used later on the LHS of a rule in other conditional elements or on the RHS of a rule as an argument to an action.
(data 1.0 blue “red”) (data 1 blue) (data 1 blue red) (data 1 blue RED) (data 1 blue red 6.9))
(slot name) (slot age) (multislot friends))
(person (name Joe) (age 20)) (person (name Bob) (age 20)) (person (name Joe) (age 34)) (person (name Sue) (age 34)) (person (name Sue) (age 20))) 5.4.1.1 Literal ConstraintsThe most basic constraint which can be used in a pattern CE is one which precisely defines the exact value that will match a field. This is called a literal constraint. A literal pattern CE consists entirely of constants such as floats, integers, symbols, strings, and instance names. It does not contain any variables or wildcards. All constraints in a literal pattern must be matched exactly by all fields of a pattern entity.
An ordered pattern conditional element containing only literals has the following basic syntax:
Example 1 This example utilizes the data facts deffacts shown in section 5.4.1.
CLIPS> (defrule find-data (data 1 blue red) ⇒) CLIPS> (reset) CLIPS> (agenda) 0 find-data: f-3 For a total of 1 activation. CLIPS> (facts) f-0 (initial-fact) f-1 (data 1.0 blue “red”) f-2 (data 1 blue) f-3 (data 1 blue red) f-4 (data 1 blue RED) f-5 (data 1 blue red 6.9) For a total of 6 facts. CLIPS> Example 2 This example utilizes the person deftemplate and people deffacts shown in section 5.4.1.
CLIPS> (defrule Find-Bob (person (name Bob) (age 20)) ⇒) CLIPS> (defrule Find-Sue (person (age 34) (name Sue)) ⇒) CLIPS> (reset) CLIPS> (agenda) 0 Find-Sue: f-4 0 Find-Bob: f-2 For a total of 2 activations. CLIPS> (facts) f-0 (initial-fact) f-1 (person (name Joe) (age 20) (friends)) f-2 (person (name Bob) (age 20) (friends)) f-3 (person (name Joe) (age 34) (friends)) f-4 (person (name Sue) (age 34) (friends)) f-5 (person (name Sue) (age 20) (friends)) For a total of 6 facts. CLIPS> 5.4.1.2 Wildcards Single and MultifieldCLIPS has two wildcard symbols that may be used to match fields in a pattern. CLIPS interprets these wildcard symbols as standing in place of some part of a pattern entity. The single field wildcard, denoted by a question mark character (?), matches any value stored in exactly one field in the pattern entity. The multifield wildcard, denoted by a dollar sign followed by a question mark ($?), matches any value in zero or more fields in a pattern entity. Single field and multifield wildcards may be combined in a single pattern in any combination. It is illegal to use a multifield wildcard in a single field slot of a deftemplate or object pattern. By default, an unspecified single field slot in a deftemplate/object pattern is matched against an implied single field wildcard. Similarly, an unspecified multifield slot in a deftemplate/object pattern is matched against an implied multifield wildcard.
An ordered pattern conditional element containing only literals and wildcards has the following basic syntax:
Example 1 This example utilizes the data facts deffacts shown in section 5.4.1.
CLIPS> (defrule find-data (data ? blue red $?) ⇒) CLIPS> (reset) CLIPS> (agenda) 0 find-data: f-5 0 find-data: f-3 For a total of 2 activations. CLIPS> (facts) f-0 (initial-fact) f-1 (data 1.0 blue “red”) f-2 (data 1 blue) f-3 (data 1 blue red) f-4 (data 1 blue RED) f-5 (data 1 blue red 6.9) For a total of 6 facts. CLIPS> Example 2 This example utilizes the person deftemplate and people deffacts shown in section 5.4.1.
CLIPS> (defrule match-all-persons (person) ⇒) CLIPS> (reset) CLIPS> (agenda) 0 match-all-persons: f-5 0 match-all-persons: f-4 0 match-all-persons: f-3 0 match-all-persons: f-2 0 match-all-persons: f-1 For a total of 5 activations. CLIPS> (facts) f-0 (initial-fact) f-1 (person (name Joe) (age 20) (friends)) f-2 (person (name Bob) (age 20) (friends)) f-3 (person (name Joe) (age 34) (friends)) f-4 (person (name Sue) (age 34) (friends)) f-5 (person (name Sue) (age 20) (friends)) For a total of 6 facts. CLIPS>
(data YELLOW red) (data red YELLOW) (data YELLOW) (data YELLOW data YELLOW)
5.4.1.3 Variables Single and MultifieldWildcard symbols replace portions of a pattern and accept any value. The value of the field being replaced may be captured in a variable for comparison, display, or other manipulations. This is done by directly following the wildcard symbol with a variable name.
Expanding on the syntax definition given in section 5.4.1.2 now gives:
<single-field-variable> | <multifield-variable>
Example 1 CLIPS> (clear) CLIPS> (reset) CLIPS> (assert (data 2 blue green) (data 1 blue) (data 1 blue red)) <Fact-3> CLIPS> (facts) f-0 (initial-fact) f-1 (data 2 blue green) f-2 (data 1 blue) f-3 (data 1 blue red) For a total of 4 facts. CLIPS> (defrule find-data-1 (data ?x ?y ?z) ⇒ (printout t ?x ” : “ ?y ” : “ ?z crlf)) CLIPS> (run) 1 : blue : red 2 : blue : green CLIPS> Example 2 CLIPS> (reset) CLIPS> (assert (data 1 blue) (data 1 blue red) (data 1 blue red 6.9)) <Fact-3> CLIPS> (facts) f-0 (initial-fact) f-1 (data 1 blue) f-2 (data 1 blue red) f-3 (data 1 blue red 6.9) For a total of 4 facts. CLIPS> (defrule find-data-1 (data ?x $?y ?z) ⇒ (printout t ”?x = “ ?x crlf ”?y = “ ?y crlf ”?z = “ ?z crlf ”——“ crlf)) CLIPS> (run) ?x = 1 ?y = (blue red) ?z = 6.9 ------ ?x = 1 ?y = (blue) ?z = red ------ ?x = 1 ?y = () ?z = blue ------ CLIPS>
Example 3 CLIPS> (clear) CLIPS> (deffacts data (data red green) (data purple blue) (data purple green) (data red blue green) (data purple blue green) (data purple blue brown)) CLIPS> (defrule find-data-1 (data red ?x) (data purple ?x) ⇒) CLIPS> (defrule find-data-2 (data red $?x) (data purple $?x) ⇒) CLIPS> (reset) CLIPS> (facts) f-0 (initial-fact) f-1 (data red green) f-2 (data purple blue) f-3 (data purple green) f-4 (data red blue green) f-5 (data purple blue green) f-6 (data purple blue brown) For a total of 7 facts. CLIPS> (agenda) 0 find-data-2: f-4,f-5 0 find-data-1: f-1,f-3 0 find-data-2: f-1,f-3 For a total of 3 activations. CLIPS> 5.4.1.4 Connective ConstraintsThree connective constraints are available for connecting individual constraints and variables to each other. These are the & (and), | (or), and ~ (not) connective constraints. The & constraint is satisfied if the two adjoining constraints are satisfied. The | constraint is satisfied if either of the two adjoining constraints is satisfied. The ~ constraint is satisfied if the following constraint is not satisfied. The connective constraints can be combined in almost any manner or number to constrain the value of specific fields while pattern matching. The ~ constraint has highest precedence, followed by the & constraint, followed by the | constraint. Otherwise, evaluation of multiple constraints can be considered to occur from left to right. There is one exception to the precedence rules which applies to the binding occurrence of a variable. If the first constraint is a variable followed by an & connective constraint, then the first constraint is treated as a separate constraint which also must be satisified. Thus the constraint ?x&red|blue is treated like ?x&(red|blue) rather than (?x&red)|blue as the normal precedence rules would indicate. Basic Syntax Connective constraints have the following basic syntax:
Expanding on the syntax definition given in section 5.4.1.3 now gives:
::= <single-constraint> | <single-constraint> & <connected-constraint> | <single-constraint> | <connected-constraint>
<single-field-variable> | <multifield-variable>
Example 1 CLIPS> (clear) CLIPS> (deftemplate data-B (slot value)) CLIPS> (deffacts AB (data-A green) (data-A blue) (data-B (value red)) (data-B (value blue))) CLIPS> (defrule example1-1 (data-A ~blue) ⇒) CLIPS> (defrule example1-2 (data-B (value ~red&~green)) ⇒) CLIPS> (defrule example1-3 (data-B (value green|red)) ⇒) CLIPS> (reset) CLIPS> (facts) f-0 (initial-fact) f-1 (data-A green) f-2 (data-A blue) f-3 (data-B (value red)) f-4 (data-B (value blue)) For a total of 5 facts. CLIPS> (agenda) 0 example1-2: f-4 0 example1-3: f-3 0 example1-1: f-1 For a total of 3 activations. CLIPS> Example 2 CLIPS> (clear) CLIPS> (deftemplate data-B (slot value)) CLIPS> (deffacts B (data-B (value red)) (data-B (value blue))) CLIPS> (defrule example2-1 (data-B (value ?x&~red&~green)) ⇒ (printout t ”?x in example2-1 = “ ?x crlf)) CLIPS> (defrule example2-2 (data-B (value ?x&green|red)) ⇒ (printout t ”?x in example2-2 = “ ?x crlf)) CLIPS> (reset) CLIPS> (run) ?x in example2-1 = blue ?x in example2-2 = red CLIPS> Example 3 CLIPS> (clear) CLIPS> (deftemplate data-B (slot value)) CLIPS> (deffacts AB (data-A green) (data-A blue) (data-B (value red)) (data-B (value blue))) CLIPS> (defrule example3-1 (data-A ?x&~green) (data-B (value ?y&~?x)) ⇒) CLIPS> (defrule example3-2 (data-A ?x) (data-B (value ?x&green|blue)) ⇒) CLIPS> (defrule example3-3 (data-A ?x) (data-B (value ?y&blue|?x)) ⇒) CLIPS> (reset) CLIPS> (facts) f-0 (initial-fact) f-1 (data-A green) f-2 (data-A blue) f-3 (data-B (value red)) f-4 (data-B (value blue)) For a total of 5 facts. CLIPS> (agenda) 0 example3-3: f-1,f-4 0 example3-3: f-2,f-4 0 example3-2: f-2,f-4 0 example3-1: f-2,f-3 For a total of 4 activations. CLIPS> 5.4.1.5 Predicate ConstraintsSometimes it becomes necessary to constrain a field based upon the truth of a given boolean expression. CLIPS allows the use of a predicate constraint to restrict a field in this manner. The predicate constraint allows a predicate function (one returning the symbol FALSE for unsatisfied and a non FALSE value for satisfied) to be called during the pattern matching process. If the predicate function returns a non FALSE value, the constraint is satisfied. If the predicate function returns the symbol FALSE, the constraint is not satisfied. A predicate constraint is invoked by following a colon with an appropriate function call to a predicate function. Typically, predicate constraints are used in conjunction with a connective constraint and a variable binding (i.e. you have to bind the variable to be tested and then connect it to the predicate constraint). Basic Syntax :<function-call>
Expanding on the syntax definition given in section 5.4.1.4 now gives:
<single-field-variable> | <multifield-variable> | :<function-call>
Example 1 CLIPS> (clear) CLIPS> (defrule example-1 (data ?x&:(numberp ?x)) ⇒) CLIPS> (assert (data 1) (data 2) (data red)) <Fact-2> CLIPS> (agenda) 0 example-1: f-1 0 example-1: f-0 For a total of 2 activations. CLIPS> Example 2 CLIPS> (clear) CLIPS> (defrule example-2 (data ?x&~:(symbolp ?x)) ⇒) CLIPS> (assert (data 1) (data 2) (data red)) <Fact-2> CLIPS> (agenda) 0 example-2: f-1 0 example-2: f-0 For a total of 2 activations. CLIPS> Example 3 CLIPS> (clear) CLIPS> (defrule example-3 (data ?x&:(numberp ?x)&:(oddp ?x)) ⇒) CLIPS> (assert (data 1) (data 2) (data red)) <Fact-2> CLIPS> (agenda) 0 example-3: f-0 For a total of 1 activation. CLIPS> Example 4 CLIPS> (clear) CLIPS> (defrule example-4 (data ?y) (data ?x&:(> ?x ?y)) ⇒) CLIPS> (assert (data 3) ; f-0 (data 5) ; f-1 (data 9)) ; f-2 <Fact-2> CLIPS> (agenda) 0 example-4: f-0,f-2 0 example-4: f-1,f-2 0 example-4: f-0,f-1 For a total of 3 activations. CLIPS> Example 5 CLIPS> (clear) CLIPS> (defrule example-5 (data $?x&:(> (length$ ?x) 2)) ⇒) CLIPS> (assert (data 1) ; f-0 (data 1 2) ; f-1 (data 1 2 3)) ; f-2 <Fact-2> CLIPS> (agenda) 0 example-5: f-2 For a total of 1 activation. CLIPS> 5.4.1.6 Return Value ConstraintsIt is possible to use the return value of an external function to constrain the value of a field. The return value constraint ( allows the user to call external functions from inside a pattern. (This constraint is different from the comparison function which uses the same symbol. The difference can be determined from context.) The return value must be one of the primitive data types. This value is incorporated directly into the pattern at the position at which the function was called as if it were a literal constraint, and any matching patterns must match this value as though the rule were typed with that value. Note that the function is evaluated each time the constraint is checked (not just once). Basic Syntax =<function-call>
Expanding on the syntax definition given in section 5.4.1.5 now gives:
<single-field-variable> | <multifield-variable> | :<function-call> | =<function-call> Example 1 CLIPS> (clear) CLIPS> (deftemplate data (slot x) (slot y)) CLIPS> (defrule twice (data (x ?x) (y =(* 2 ?x))) ⇒) CLIPS> (assert (data (x 2) (y 4)) ; f-0 (data (x 3) (y 9))) ; f-1 <Fact-1> CLIPS> (agenda) 0 twice: f-0 For a total of 1 activation. CLIPS> Example 2 CLIPS> (clear) CLIPS> (defclass DATA (is-a USER) (role concrete) (pattern-match reactive) (slot x (create-accessor write))) CLIPS> (defrule return-value-example-2 (object (is-a DATA) (x ?x1)) (object (is-a DATA) (x ?x2&=(+ 5 ?x1)|=(- 12 ?x1))) ⇒) CLIPS> (make-instance of DATA (x 4)) [gen1] CLIPS> (make-instance of DATA (x 9)) [gen2] CLIPS> (make-instance of DATA (x 3)) [gen3] CLIPS> (agenda) 0 return-value-example-2: [gen3],[gen2] 0 return-value-example-2: [gen2],[gen3] 0 return-value-example-2: [gen1],[gen2] For a total of 3 activations. CLIPS> 5.4.1.7 Pattern Matching with Object PatternsInstances of user defined classes in COOL can be pattern matched on the left hand side of rules. Patterns can only match objects for which the object’s most specific class is defined before the pattern and which are in scope for the current module. Any classes which could have objects which match the pattern cannot be deleted or changed until the pattern is deleted. Even if a rule is deleted by its RHS, the classes bound to its patterns cannot be changed until after the RHS finishes executing.
<object-pattern> ::= (object <attribute-constraint>*)
(name <constraint>) | (<slot-name> <constraint>*)
Example 1 The following rules illustrate pattern matching on an object's class.
(object) ⇒)
(object (is-a FOO)) ⇒)
(object (is-a FOO | BAR)) ⇒)
(object (is-a ?x)) (object (is-a ~?x)) ⇒)
Example 2 The following rules illustrate pattern matching on various attributes of an object's slots.
(object (width)) ⇒)
(object (width ?)) ⇒)
(object (width $?)) ⇒)
Example 3 The following rules illustrate pattern matching on the slot values of an object.
(object (width 10) ⇒)
(object (width ?x&:(> ?x 20))) ⇒)
(object (width ?x) (height ?x)) ⇒)
5.4.1.8 Pattern AddressesCertain RHS actions, such as retract and unmake instance, operate on an entire pattern CE. To signify which fact or instance they are to act upon, a variable can be bound to the fact address or instance address of a pattern CE. Collectively, fact addresses and instance addresses bound on the LHS of a rule are referred to as pattern addresses. Syntax <assigned-pattern-CE> ::= ?<variable-symbol> ← <pattern-CE>
Examples (defrule dummy (data 1) ?fact ← (dummy pattern) ⇒ (retract ?fact))
?f1 ← (color ~red) ?f2 ← (color ~green) (test (neq ?f1 ?f2)) ⇒ (printout t “Rule fires from different facts” crlf))
?f1 ← (color ~red) ?f2 ← (color ~green&:(neq ?f1 ?f2)) ⇒ (printout t “Rule fires from different facts” crlf))
?ins ← (object) ⇒ (send ?ins print) (unmake-instance ?ins)) 5.4.2 Test Conditional ElementField constraints used within pattern CEs allow very descriptive constraints to be applied to pattern matching. Additional capability is provided with the test conditional element. The test CE is satisfied if the function call within the test CE evaluates to a non FALSE value and unsatisfied if the function call evaluates to FALSE. As with predicate constraints, the user can compare the variable bindings that already have occurred in any manner. Mathematical comparisons on variables (e.g., is the difference between ?x and ?y greater than some value?) and complex logical or equality comparisons can be done. External functions also can be called which compare variables in any way that the user desires.
Syntax <test-CE> ::= (test <function-call>)
Example 1 This example checks to see if the difference between two numbers is greater than or equal to three:
CLIPS> (defrule example-1 (data ?x) (value ?y) (test (>= (abs (- ?y ?x)) 3)) ⇒) CLIPS> (assert (data 6) (value 9)) <Fact-1> CLIPS> (agenda) 0 example-1: f-0,f-1 For a total of 1 activation. CLIPS> Example 2 This example checks to see if there is a positive slope between two points on a line.
CLIPS> (deffunction positive-slope (?x1 ?y1 ?x2 ?y2) (< 0 (/ (- ?y2 ?y1) (- ?x2 ?x1)))) CLIPS> (defrule example-2 (point ?a ?x1 ?y1) (point ?b ?x2 ?y2) (test (> ?b ?a)) (test (positive-slope ?x1 ?y1 ?x2 ?y2)) ⇒) CLIPS> (assert (point 1 4.0 7.0) (point 2 5.0 9.0)) <Fact-1> CLIPS> (agenda) 0 example-2: f-0,f-1 For a total of 1 activation. CLIPS>
Because the test CE can cause the addition of the initial fact fact pattern or the initial object instance pattern to a rule, a reset command (which creates the initial fact fact and the initial object instance) must be issued for the correct operation of the test CE under all circumstances. 5.4.3 Or Conditional ElementThe or conditional element allows any one of several conditional elements to activate a rule. If any of the conditional elements inside of the or CE is satisfied, then the or CE is satisfied. If all other LHS conditional elements are satisfied, the rule will be activated. Note that a rule will be activated for each conditional element with an or CE that is satisfied (assuming the other conditional elements of the rule are also satisfied). Any number of conditional elements may appear within an or CE. The or CE produces the identical effect of writing several rules with similar LHS’s and RHS’s. Syntax
<or-CE> ::= (or <conditional-element>+) Again, if more than one of the conditional elements in the or CE can be met, the rule will fire multiple times, once for each satisfied combination of conditions. Example
(defrule system-fault
(pump (status off)))
5.4.4 And Conditional ElementCLIPS assumes that all rules have an implicit and conditional element surrounding the conditional elements on the LHS. This means that all conditional elements on the LHS must be satisfied before the rule can be activated. An explicit and conditional element is provided to allow the mixing of and CEs and or CEs. This allows other types of conditional elements to be grouped together within or and not CEs. The and CE is satisfied if all of the CEs inside of the explicit and CE are satisfied. If all other LHS conditions are true, the rule will be activated. Any number of conditional elements may be placed within an and CE. Syntax <and-CE> ::= (and <conditional-element>+) Example
(defrule system-flow
(not (schedule ?)) ⇒ (printout t “Nothing to schedule.” crlf))
(and (initial-fact) (not (schedule ?))) ⇒ (printout t “Nothing to schedule.” crlf)) 5.4.5 Not Conditional ElementSometimes the lack of information is meaningful; i.e., one wishes to fire a rule if a pattern entity or other CE does not exist. The not conditional element provides this capability. The not CE is satisfied only if the conditional element contained within it is not satisfied. As with other conditional elements, any number of additional CEs may be on the LHS of the rule and field constraints may be used within the negated pattern. Syntax <not-CE> ::= (not <conditional-element>)
Examples
(defrule high-flow-rate crlf))
(not (data red ?x ?x))
(test (> ?time-1 ?time-2))))
Because the not CE can cause the addition of the initial fact fact pattern or the initial object instance pattern to a rule, a reset command (which creates the initial fact fact and the initial object instance) must be issued for the correct operation of the not CE under all circumstances. 5.4.6 Exists Conditional ElementThe exists conditional element provides a mechanism for determining if a group of specified CEs is satisfied by a least one set of pattern entities. Syntax <exists-CE> ::= (exists <conditional-element>+)
(exists (a ?x) (b ?x)) ⇒)
(not (not (and (a ?x) (b ?x)))) ⇒)
Example Given the following constructs,
CLIPS> (deftemplate hero (multislot name) (slot status (default unoccupied))) CLIPS> (deffacts goal-and-heroes (goal save-the-day) (hero (name Death Defying Man)) (hero (name Stupendous Man)) (hero (name Incredible Man))) CLIPS> (defrule save-the-day (goal save-the-day) (exists (hero (status unoccupied))) ⇒ (printout t “The day is saved.” crlf)) CLIPS>
CLIPS> (agenda) 0 save-the-day: f-1, For a total of 1 activation. CLIPS> (facts) f-0 (initial-fact) f-1 (goal save-the-day) f-2 (hero (name Death Defying Man) (status unoccupied)) f-3 (hero (name Stupendous Man) (status unoccupied)) f-4 (hero (name Incredible Man) (status unoccupied)) For a total of 5 facts. CLIPS> (matches save-the-day) Matches for Pattern 1 f-1 Matches for Pattern 2 f-0 Matches for Pattern 3 f-2 f-3 f-4 Partial matches for CEs 1 - 2 f-1, Activations f-1, CLIPS>
The exists CE is implemented using the not CE. Because the not CE can cause the addition of the initial fact fact pattern or the initial object instance pattern to a rule, a reset command (which creates the initial fact fact and the initial object instance) must be issued for the correct operation of the exists CE under all circumstances. 5.4.7 Forall Conditional ElementThe forall conditional element provides a mechanism for determining if a group of specified CEs is satisfied for every occurence of another specified CE. Syntax <forall-CE> ::= (forall <conditional-element> <conditional-element>+)
(forall (a ?x) (b ?x) (c ?x)) ⇒)
(not (and (a ?x) (not (and (b ?x) (c ?x))))) ⇒)
Example The following rule determines if every student has passed in reading, writing, and arithmetic by using the forall CE.
CLIPS> (defrule all-students-passed (forall (student ?name) (reading ?name) (writing ?name) (arithmetic ?name)) ⇒ (printout t “All students passed.” crlf)) CLIPS>
CLIPS> (agenda) 0 all-students-passed: f-0, For a total of 1 activation. CLIPS>
<Fact-1> CLIPS> (agenda) CLIPS>
<Fact-3> CLIPS> (agenda) CLIPS>
<Fact-4> CLIPS> (agenda) 0 all-students-passed: f-0, For a total of 1 activation. CLIPS>
<Fact-5> CLIPS> (agenda) CLIPS>
CLIPS> (agenda) 0 all-students-passed: f-0, For a total of 1 activation. CLIPS>
The forall CE is implemented using the not CE. Because the not CE can cause the addition of the initial fact fact pattern or the initial object instance pattern to a rule, a reset command (which creates the initial fact fact and the initial object instance) must be issued for the correct operation of the forall CE under all circumstances. 5.4.8 Logical Conditional ElementThe logical conditional element provides a truth maintenance capability for pattern entities (facts or instances) created by rules which use the logical CE. A pattern entity created on the RHS (or as a result of actions performed from the RHS) can be made logically dependent upon the pattern entities which matched the patterns enclosed with the logical CE on the LHS of the rule. The pattern entities matching the LHS logical patterns provide logical support to the facts and instance created by the RHS of the rule. A pattern entity can be logically supported by more than one group of pattern entities from the same or different rules. If any one supporting pattern entities is removed from a group of supporting pattern entities (and there are no other supporting groups), then the pattern entity is removed.
Syntax <logical-CE> ::= (logical <conditional-element>+)
(logical (a)) (logical (b)) © ⇒ (assert (d)))
(logical (a)) (b) (logical ©) ⇒ (assert (d)))
(a) (logical (b)) (logical ©) ⇒ (assert (d)))
(or (a) (logical (b))) (logical ©) ⇒ (assert (d))) Example Given the following rules,
CLIPS> (defrule rule1 (logical (a)) (logical (b)) © ⇒ (assert (g) (h))) CLIPS> (defrule rule2 (logical (d)) (logical (e)) (f) ⇒ (assert (g) (h))) CLIPS>
CLIPS> (watch activations) CLIPS. (watch rules) CLIPS> (assert (a) (b) © (d) (e) (f)) ==> f-0 (a) ==> f-1 (b) ==> f-2 © ==> Activation 0 rule1: f-0,f-1,f-2 ==> f-3 (d) ==> f-4 (e) ==> f-5 (f) ==> Activation 0 rule2: f-3,f-3,f-5 <Fact-5> CLIPS> (run) FIRE 1 rule2: f-3,f-4,f-5 ; 1st rule adds logical support ==> f-6 (g) ==> f-7 (h) FIRE 2 rule1: f-0,f-1,f-2 ; 2nd rule adds further support CLIPS> (retract 1) ⇐= f-0 (a) ; Removes 1st support for (g) and (h) CLIPS> (assert (h)) ; (h) is unconditionally supported FALSE CLIPS> (retract 3) ⇐= f-3 (d) ; Removes 2nd support for (g) ⇐= f-6 (g) ; (g) has no more support CLIPS> (unwatch all) CLIPS>
CLIPS> (defclass A (is-a USER) (role concrete) (pattern-match reactive) (slot foo (create-accessor write)) (slot bar (create-accessor write))) CLIPS> (deftemplate A (slot foo) (slot bar)) CLIPS> (defrule match-A-s (logical (object (is-a A) (foo ?)) (A (foo ?))) ⇒ (assert (new-fact))) CLIPS> (make-instance a of A) [a] CLIPS> (assert (A)) <Fact-0> CLIPS> (watch facts) CLIPS> (run) ==> f-1 (new-fact) CLIPS> (send [a] put-bar 100) 100 CLIPS> (agenda) CLIPS> (modify 0 (bar 100)) ⇐= f-0 (A (foo nil) (bar nil)) ⇐= f-1 (new-fact) ==> f-2 (A (foo nil) (bar 100)) <Fact-2> CLIPS> (agenda) 0 match-A-s: [a],f-2 For a total of 1 activation. CLIPS> (run) ==> f-3 (new-fact) CLIPS> (send [a] put-foo 100) ⇐= f-3 (new-fact) 100 CLIPS> (agenda) 0 match-A-s: [a],f-2 For a total of 1 activation. CLIPS> (unwatch facts) CLIPS> 5.4.9 Automatic Addition and Reordering of LHS CEsUnder certain circumstances, CLIPS adds additional pattern CEs to rules (usually for the benefit of the pattern matching algorithm used by CLIPS). There are two default patterns used by CLIPS: the initial fact fact pattern and the initial object instance pattern. The initial fact pattern is
5.4.9.1 Rules Without Any LHS Pattern CEsThe initial fact pattern is added to any rule that has no patterns on its LHS (unless facts have been disabled by configuring CLIPS in which case the initial object pattern is added to the LHS of the rule). For example, the following rule
⇒)
(initial-fact) ⇒) 5.4.9.2 Test and Not CEs as the First CE of an And CETest CEs and not CEs that are the first CE within an and CE have an initial fact or an initial object pattern added immediately before them. An initial fact pattern is added if the first pattern CE preceding the CE in question is a fact pattern. An initial object pattern is added if the first pattern CE preceding the CE in question is an object pattern. If there are no preceding pattern CEs, the type of pattern is determined by the succeeding pattern CEs using the same methodology. If there are no pattern CEs in the rule at all, then an initial fact pattern is placed before the CE in question (unless facts have been disabled by configuring CLIPS in which case the initial object pattern is added before the CE). For example, the following rules
(test (> 80 (startup-value))) ⇒)
(test (> 80 (startup-value))) (object (is-a MACHINE)) ⇒)
(machine ?x) (not (and (not (part ?x ?y)) (inventoried ?x))) ⇒)
(initial-fact) (test (> 80 (startup-value))) ⇒)
(object (is-a INITIAL-OBJECT) (name [initial-object])) (test (> 80 (startup-value))) (object (is-a MACHINE)) ⇒)
(machine ?x) (not (and (initial-fact) (not (part ?x ?y)) (inventoried ?x))) ⇒) 5.4.9.3 Test CEs Following Not CEsTest CEs that immediately follow a not CE are automatically moved by CLIPS behind the first pattern CE that precedes the not CE. For example, the following rule
(a ?x) (not (b ?x)) (test (> ?x 5)) ⇒)
(a ?x) (test (> ?x 5)) (not (b ?x)) ⇒) 5.4.9.4 Or CEs Following Not CEsIf an or CE immediately follows a not CE, then the not/or CE combination is replaced with an and/not CE combination where each of the CEs contained in the original or CE is enclosed within a not CE and then all of the not CEs are enclosed within a single and CE. For example, the following rule
(a ?x) (not (or (b ?x) (c ?x))) ⇒)
(a ?x) (and (not (b ?x)) (not (c ?x))) ⇒) 5.4.9.5 Notes About Pattern Addition and ReorderingThere are several points which should be noted about the addition and reordering of pattern CEs: 1) The entire LHS of a rule is considered to be within an implicit and CE; 2) The conversion of the forall and exists CEs to equivalent not and and CEs is performed before patterns are added to the LHS of a rule; 3) In general, it is not very useful to have a test CE as the first CE within an and CE; and 4) The output of commands such as the matches command display information for the CEs that are actually added to the LHS of a rule and, because of reordering and implicit additions, may not reflect the rule exactly as defined by the user. 5.4.10 Declaring Rule PropertiesThis feature allows the properties or characteristics of a rule to be defined. The characteristics are declared on the LHS of a rule using the declare keyword. A rule may only have one declare statement and it must appear before the first conditional element on the LHS (as shown in section 5.1). Syntax <declaration> ::= (declare <rule-property>+)
(auto-focus <boolean-symbol>)
5.4.10.1 The Salience Rule PropertyThe salience rule property allows the user to assign a priority to a rule. When multiple rules are in the agenda, the rule with the highest priority will fire first. The declared salience value should be an expression that evaluates to an an integer in the range 10000 to +10000. Salience expressions may freely reference global variables and other functions (however, you should avoid using functions with side effects). If unspecified, the salience value for a rule defaults to zero. Example
(defrule test-1
(fire test-2)
5.4.10.2 The Auto Focus Rule PropertyThe auto focus rule property allows an automatic focus command to be executed whenever a rule becomes activated. If the auto focus property for a rule is TRUE, then a focus command on the module in which the rule is defined is automatically executed whenever the rule is activated. If the auto focus property for a rule is FALSE, then no action is taken when the rule is activated. If unspecified, the auto focus value for a rule defaults to FALSE. Example
(defrule VIOLATIONS::bad-age Section 6 Defglobal ConstructWith the defglobal construct, global variables can be defined, set, and accessed within the CLIPS environment. Global variables can be accessed as part of the pattern matching process, but changing them does not invoke the pattern matching process. The bind function is used to set the value of global variables. Global variables are reset to their original value when the reset command is performed or when bind is called for the global with no values. This behavior can be changed using the set reset globals function. Global variables can be removed by using the clear command or the undefglobal command. If the globals item is being watched (see section 13.2), then an informational message will be displayed each time the value of a global variable is changed. Syntax (defglobal [<defmodule-name>] <global-assignment>*)
(fact ?*x*) ⇒)
(fact ?y&:(> ?y ?*x*)) ⇒)
Example (defglobal ?*x* = 3 ?*y* = ?*x* ?*z* = (+ ?*x* ?*y*) ?*q* = (create$ a b c))
Section 7 Deffunction ConstructWith the deffunction construct, new functions may be defined directly in CLIPS. Deffunctions are equivalent in use to other functions; see section 2.3.2 for more detail on calling functions in CLIPS. The only differences between user defined external functions and deffunctions are that deffunctions are written in CLIPS and executed by CLIPS interpretively and user defined external functions are written in an external language, such as C, and executed by CLIPS directly. Also, deffunctions allow the addition of new functions without having to recompile and relink CLIPS.
Syntax (deffunction <name> [<comment>] (<regular-parameter>* [<wildcard-parameter>]) <action>*)
<wildcard-parameter> ::= <multifield-variable>
Example CLIPS> (clear) CLIPS> (deffunction print-args (?a ?b $?c) (printout t ?a ” “ ?b ” and “ (length ?c) ” extras: “ ?c crlf)) CLIPS> (print-args 1 2) 1 2 and 0 extras: () CLIPS> (print-args a b c d) a b and 2 extras: (c d) CLIPS>
Example (deffunction factorial (?a) (if (or (not (integerp ?a)) (< ?a 0)) then (printout t “Factorial Error!” crlf) else (if (= ?a 0) then 1 else (* ?a (factorial (- ?a 1))))))
Example (deffunction foo ()) (deffunction bar () (foo)) (deffunction foo () (bar))
Section 8 Generic FunctionsWith the defgeneric and defmethod constructs, new genericfunctions may be written directly in CLIPS. Generic functions are similar to deffunctions because they can be used to define new procedural code directly in CLIPS, and they can be called like any other function (see sections 2.3.2 and 7). However, generic functions are much more powerful because they can do different things depending on the types (or classes) and number of their arguments. For example, a “+” operator could be defined which performs concatenation for strings but still performs arithmetic addition for numbers. Generic functions are comprised of multiple components called methods, where each method handles different cases of arguments for the generic function. A generic function which has more than one method is said to be overloaded.
8.1 Note on the Use of the Term MethodMost OOP systems support procedural behavior of objects either through message passing (e.g. Smalltalk) or by generic functions (e.g. CLOS). CLIPS supports both of these mechanisms, although generic functions are not strictly part of COOL. A generic function may examine the classes of its arguments but must still use messages within the bodies of its methods to manipulate any arguments which are instances of user defined classes. Section 9 gives more details on COOL. The fact that CLIPS supports both mechanisms leads to a confusion in terminology. In OOP systems which support message passing only, the term method is used to denote the different implementations of a message for different classes. In systems which support generic functions only, however, the term method is used to denote the different implementations of a generic function for different sets of argument restrictions. To avoid this confusion, the term message handleris used to take the place of method in the context of messages. Thus in CLIPS, message handlers denote the different implementations of a message for different classes, and methods denote the different implementations of a generic function for different sets of argument restrictions. 8.2 Performance Penalty of Generic FunctionsA call to a generic function is computationally more expensive than a call to a system function, user defined external function or deffunction. This is because CLIPS must first examine the function arguments to determine which method is applicable. A performance penalty of 15% 20% is not unexpected. Thus, generic functions should not be used for routines for which time is critical, such as routines which are called within a while loop, if at all possible. Also, generic functions should always have at least two methods. Deffunctions or user defined external functions should be used when overloading is not required. A system or user defined external function which is not overloaded will, of course, execute as quickly as ever, since the generic dispatch is unnecessary. 8.3 Order Dependence of Generic Function DefinitionsIf a construct which uses a system or user defined external function is loaded before a generic function which uses that function as an implicit method, all calls to that function from that construct will bypass the generic dispatch. For example, if a generic function which overloads the “+” operator is defined after a rule which uses the “+” operator, that rule will always call the “+” system function directly. However, similar rules defined after the generic function will use the generic dispatch. 8.4 Defining a New Generic FunctionA generic function is comprised of a header (similar to a forward declaration) and zero or more methods. A generic function header can either be explicitly declared by the user or implicitly declared by the definition of at least one method. A method is comprised of six elements: 1) a name (which identifies to which generic function the method belongs), 2) an optional index, 3) an optional comment , 4) a set of parameter restrictions, 5) an optional wildcard parameter restriction to handle a variable number of arguments and 6) a sequence of actions, or expressions, which will be executed in order when the method is called. The parameter restrictions are used by the generic dispatch to determine a method’s applicability to a set of arguments when the generic function is actually called. The defgeneric construct is used to specify the generic function header, and the defmethod construct is used for each of the generic function’s methods.
(defgeneric <name> [<comment>])
(<parameter-restriction>* [<wildcard-parameter-restriction>]) <action>*)
<single-field-variable> | (<single-field-variable> <type>* [<query>])
<multifield-variable> | (<multifield-variable> <type>* [<query>])
<query> ::= <global-variable> | <function-call>
8.4.1 Generic Function HeadersA generic function is uniquely identified by name. In order to reference a generic function in other constructs before any of its methods are declared, an explicit header is necessary. Otherwise, the declaration of the first method implicitly creates a header. For example, two generic functions whose methods mutually call the other generic function (mutually recursive generic functions) would require explicit headers. 8.4.2 Method IndicesA method is uniquely identified by name and index, or by name and parameter restrictions. Each method for a generic function is assigned a unique integer index within the group of all methods for that generic function. Thus, if a new method is defined which has exactly the same name and parameter restrictions as another method, CLIPS will automatically replace the older method. However, any difference in parameter restrictions will cause the new method to be defined in addition to the older method. To replace an old method with one that has different parameter restrictions, the index of the old method can be explicitly specified in the new method definition. However, the parameter restrictions of the new method must not match that of another method with a different index. If an index is not specified, CLIPS assigns an index that has never been used by any method (past or current) of this generic function. The index assigned by CLIPS can be determined with the list defmethods command (see section 13.10.4). 8.4.3 Method Parameter RestrictionsEach parameter for a method can be defined to have arbitrarily complex restrictions or none at all. A parameter restriction is applied to a generic function argument at run time to determine if a particular method will accept the argument. A parameter can have two types of restrictions: type and query. A type restriction constrains the classes of arguments that will be accepted for a parameter. A query restriction is a user defined boolean test which must be satisfied for an argument to be acceptable. The complexity of parameter restrictions directly affects the speed of the generic dispatch.
Example (defmethod foo ((?a INTEGER NUMBER)))
Example (defmethod foo ((?a INTEGER) (?b INTEGER (> ?a ?b))))
Example In the following example, the first call to the generic function “+” executes the system operator “+”, an implicit method for numerical addition. The second call executes the explicit method for string concatenation, since there are two arguments and they are both strings. The third call generates an error because the explicit method for string concatenation only accepts two arguments and the implicit method for numerical addition does not accept strings at all.
CLIPS> (defmethod + ((?a STRING) (?b STRING)) (str-cat ?a ?b)) CLIPS> (+ 1 2) 3 CLIPS> (+ “foo” “bar”) “foobar” CLIPS> (+ “foo” “bar” “woz”) [GENRCEXE1] No applicable methods for +. FALSE 8.4.4 Method Wildcard ParameterA method may accept exactly or at least a specified number of arguments, depending on whether a wildcard parameter is used or not. The regular parameters specify the minimum number of arguments that must be passed to the method. Each of these parameters may be referenced like a normal single field variable within the actions of the method. If a wildcard parameter is present, the method may be passed any number of arguments greater than or equal to the minimum. If no wildcard parameter is present, then the method must be passed exactly the number of arguments specified by the regular parameters. Method arguments which do not correspond to a regular parameter can be grouped into a multifield value that can be referenced by the wildcard parameter within the body of the method. The standard CLIPS multifield functions, such as length$ and expand$, can be applied to the wildcard parameter.
Example CLIPS> (defmethod + (($?any INTEGER (evenp ?current-argument))) (div (call-next-method) 2)) CLIPS> (+ 1 2) 3 CLIPS> (+ 4 6 4) 7 CLIPS>
Example CLIPS> (defmethod foo (($?any (> (length$ ?any) 2))) yes) CLIPS> (foo 1 red 3) yes CLIPS>
Example CLIPS> (foo) yes CLIPS>
Example CLIPS> (clear) CLIPS> (defmethod foo ((?arg (> (length$ ?any) 1)) $?any) yes) CLIPS> (foo) [GENRCEXE1] No applicable methods for foo. FALSE CLIPS>
8.5 Generic DispatchWhen a generic function is called, CLIPS selects the method for that generic function with highest precedence for which parameter restrictions are satisfied by the arguments. This method is executed, and its value is returned as the value of the generic function. This entire process is referred to as the generic dispatch. Below is a flow diagram summary:
8.5.1 Applicability of Methods SummaryAn explicit (user defined) method is applicable to a generic function call if the following three conditions are met: 1) its name matches that of the generic function, 2) it accepts at least as many arguments as were passed to the generic function, and 3) every argument of the generic function satisfies the corresponding parameter restriction (if any) of the method.
…)
8.5.2 Method PrecedenceWhen two or more methods are applicable to a particular generic function call, CLIPS must pick the one with highest precedence for execution. Method precedence is determined when a method is defined; the list defmethods function can be used to examine the precedence of methods for a generic function (see section 13.10).
1b) The most specific type restriction on a particular parameter has priority. A class is more specific than any of its superclasses. 1c) A parameter with a query restriction has priority over one that does not.
Example 1 ; The system operator '+' is an implicit method ; #1 ; Its definition provided by the system is: ; (defmethod + ((?a NUMBER) (?b NUMBER) ($?rest NUMBER)))
(defmethod + ((?a INTEGER) (?b INTEGER))) ; #3 (defmethod + ((?a INTEGER) (?b NUMBER))) ; #4 (defmethod + ((?a NUMBER) (?b NUMBER) ($?rest PRIMITIVE))) ; #5 (defmethod + ((?a NUMBER) (?b INTEGER (> ?b 2)))) ; #6 (defmethod + ((?a INTEGER (> ?a 2)) (?b INTEGER (> ?b 3)))) ; #7 (defmethod + ((?a INTEGER (> ?a 2)) (?b NUMBER))) ; #8
Example 2 (defmethod foo ((?a NUMBER STRING))) ; #1 (defmethod foo ((?a INTEGER LEXEME))) ; #2
Example 3 (defmethod foo ((?a MULTIFIELD STRING))) ; #1 (defmethod foo ((?a LEXEME))) ; #2
Example 4 (defmethod foo ((?a INTEGER LEXEME))) ; #1 (defmethod foo ((?a STRING NUMBER))) ; #2
8.5.3 Shadowed MethodsIf one method must be called by another method in order to be executed, the first function or method is a said to be shadowed by the second method. Normally, only one method or system function will be applicable to a particular generic function call. If there is more than one applicable method, the generic dispatch will only execute the one with highest precedence. Letting the generic dispatch automatically handle the methods in this manner is called the declarative technique, for the declarations of the method restrictions dictate which method gets executed in specific circumstances. However, the functions call next method and override next method (see section 12.15.6 and 12.15.7) may also be used which allow a method to execute the method that it is shadowing. This is called the imperative technique, since the method execution itself plays a role in the generic dispatch. This is not recommended unless it is absolutely necessary. In most circumstances, only one piece of code should need to be executed for a particular set of arguments. Another imperative technique is to use the function call specific method to override method precedence (see section 12.15.8) 8.5.4 Method Execution ErrorsIf an error occurs while any method for a generic function call is executing, any actions in the current method not yet executed will be aborted, any methods not yet called will be aborted, and the generic function will return the symbol FALSE. The lack of any applicable methods for a set of generic function arguments is considered a method execution error. 8.5.5 Generic Function Return ValueThe return value of a generic function is the return value of the applicable method with the highest precedence. Each applicable method that is executed can choose to ignore or capture the return value of any method that it is shadowing.
Section 9 CLIPS Object Oriented Language (COOL)This section provides the comprehensive details of the CLIPS Object Oriented Language (COOL). Sections 2.3.1, 2.4.2 and 2.5.2.3 explain object references and structure. Section 2.6 gives a high level overview of COOL. This section assumes a complete understanding of the material given in the listed sections. 9.1 BackgroundCOOL is a hybrid of features from many different OOP systems as well as new ideas. For example, object encapsulation concepts are similar to those in Smalltalk, and the Common Lisp Object System (CLOS) provides the basis for multiple inheritance rules. A mixture of ideas from Smalltalk, CLOS and other systems form the foundation of messages. Section 8.1 explains an important contrast between the terms method and message handler in CLIPS. 9.2 Predefined System ClassesCOOL provides seventeen system classes: OBJECT, USER, INITIAL OBJECT, PRIMITIVE, NUMBER, INTEGER, FLOAT, INSTANCE, INSTANCE NAME, INSTANCE ADDRESS, ADDRESS, FACT ADDRESS, EXTERNAL ADDRESS, MULTIFIELD, LEXEME, SYMBOL and STRING. The user may not delete or modify any of these classes. The diagram illustrates the inheritance relationships between these classes.
9.3 Defclass ConstructA defclass is a construct for specifying the properties (slots) and behavior (message handlers) of a class of objects. A defclass consists of five elements: 1) a name, 2) a list of superclasses from which the new class inherits slots and message handlers, 3) a specifier saying whether or not the creation of direct instances of the new class is allowed, 4) a specifier saying whether or not instances of this class can match object patterns on the LHS of rules and 5) a list of slots specific to the new class. All user defined classes must inherit from at least one class, and to this end COOL provides predefined system classes for use as a base in the derivation of new classes.
Syntax Defaults are outlined.
(is-a <superclass-name>+) [<role>] [<pattern-match-role>] <slot>* <handler-documentation>*)
::= (pattern-match reactive | non-reactive)
(single-slot <name> <facet>*) | (multislot <name> <facet>*)
<access-facet> | <propagation-facet> | <source-facet> | <pattern-match-facet> | <visibility-facet> | <create-accessor-facet> <override-message-facet> | <constraint-attributes> <default-facet> ::= (default ?DERIVE | ?NONE | <expression>*) | (default-dynamic <expression>*)
::= (access read-write | read-only | initialize-only)
::= (pattern-match reactive | non-reactive)
::= (create-accessor ?NONE | read | write | read-write)
::= (override-message ?DEFAULT | <message-name>) <handler-documentation> ::= (message-handler <name> [<handler-type>])
9.3.1 Multiple InheritanceIf one class inherits from another class, the first class is a subclass of the second class, and the second class is a superclass of the first class. Every user defined class must have at least one direct superclass, i.e. at least one class must appear in the is a portion of the defclass. Multiple inheritance occurs when a class has more than one direct superclass. COOL examines the direct superclass list for a new class to establish a linear ordering called theclass precedence list. The new class inherits slots and message handlers from each of the classes in the class precedence list. The word precedence implies that slots and message handlers of a class in the list override conflicting definitions of another class found later in the list. A class that comes before another class in the list is said to be more specific. All class precedence lists will terminate in the system class OBJECT, and most (if not all) class precedence lists for user defined classes will terminate in the system classes USER and OBJECT. The class precedence list can be listed using the describe class function (see section 13.11.1.4). 9.3.1.1 Multiple Inheritance RulesCOOL uses the inheritance hierarchy of the direct superclasses to determine the class precedence list for a new class. COOL recursively applies the following two rules to the direct superclasses:
2) A class specifies the precedence between its direct superclasses.
Example 1 (defclass A (is-a USER))
Example 2 (defclass B (is-a USER))
Example 3 (defclass C (is-a A B))
Example 4 (defclass D (is-a B A))
Example 5 (defclass E (is-a A C))
Example 6 (defclass E (is-a C A))
Example 7 (defclass F (is-a C B))
Example 8 (defclass G (is-a C D))
Example 9 (defclass H (is-a A)) (defclass I (is-a B)) (defclass J (is-a H I A B))
9.3.2 Class Specifiers9.3.2.1 Abstract and Concrete ClassesAn abstract class is intended for inheritance only, and no direct instances of this class can be created. A concrete class can have direct instances. Using the abstract role specifier in a defclass will cause COOL to generate an error if make instance is ever called for this class. If the abstract or concrete descriptor for a class is not specified, it is determined by inheritance. For the purpose of role inheritance, system defined classes behave as concrete classes. Thus a class which inherits from USER will be concrete if no role is specified. 9.3.2.2 Reactive and Non Reactive ClassesObjects of a reactive class can match object patterns in a rule. Objects of a non reactive class cannot match object patterns in a rule and are not considered when the list of applicable classes are determined for an object pattern. An abstract class cannot be reactive. If the reactive or non reactive descriptor for a class is not specified, it is determined by inheritance. For the purpose of pattern-match inheritance, system defined classes behave as reactive classes unless the inheriting class is abstract. 9.3.3 SlotsSlots are placeholders for values associated with instances of a user defined class. Each instance has a copy of the set of slots specified by the immediate class as well as any obtained from inheritance. Only available memory limits the number of slots. The name of a slot may be any symbol with the exception of the keywords is a and name which are reserved for use in object patterns.
Example (defclass A (is-a USER) (slot fooA) (slot barA))
(slot fooB) (slot barB))
9.3.3.1 Slot Field TypeA slot can hold either a single field or multifield value. By default, a slot is single field. The keyword multislot specifies that a slot can hold a multifield value comprised of zero or more fields, and the keywords slot or single slot specify that the slot can hold one value. Multifield slot values are stored as multifield values and can be manipulated with the standard multifield functions, such as nth$ and length$, once they are retrieved via messages. COOL also provides functions for setting multifield slots, such as slot insert$(see section 12.16.4.12.2). Single field slots are stored as a CLIPS primitive type, such as integer or string. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (multislot foo (create-accessor read) (default abc def ghi))) CLIPS> (make-instance a of A) [a] CLIPS> (nth$ 2 (send [a] get-foo)) def CLIPS> 9.3.3.2 Default Value FacetThe default and default dynamic facets can be used to specify an initial value given to a slot when an instance of the class is created or initialized. By default, a slot will have a default value which is derived from the slot’s constraint facets (see sections 9.3.3.11 and 11.5). Default values are directly assigned to slots without the use of messages, unlike slot overrides in a make instance call (see section 9.6.1).
Example CLIPS> (clear) CLIPS> (setgen 1) 1 CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (default-dynamic (gensym)) (create-accessor read))) CLIPS> (make-instance a1 of A) [a1] CLIPS> (make-instance a2 of A) [a2] CLIPS> (send [a1] get-foo) gen1 CLIPS> (send [a2] get-foo) gen2 CLIPS> 9.3.3.3 Storage FacetThe actual value of an instance’s copy of a slot can either be stored with the instance or with the class. The local facet specifies that the value be stored with the instance, and this is the default. The shared facet specifies that the value be stored with the class. If the slot value is locally stored, then each instance can have a separate value for the slot. However, if the slot value is stored with the class, all instances will have the same value for the slot. Anytime the value is changed for a shared slot, it will be changed for all instances with that slot.
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (create-accessor write) (storage shared) (default 1)) (slot bar (create-accessor write) (storage shared) (default-dynamic 2)) (slot woz (create-accessor write) (storage local))) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] print) [a] of A (foo 1) (bar 2) (woz nil) CLIPS> (send [a] put-foo 56) 56 CLIPS> (send [a] put-bar 104) 104 CLIPS> (make-instance b of A) [b] CLIPS> (send [b] print) [b] of A (foo 56) (bar 2) (woz nil) CLIPS> (send [b] put-foo 34) 34 CLIPS> (send [b] put-woz 68) 68 CLIPS> (send [a] print) [a] of A (foo 34) (bar 2) (woz nil) CLIPS> (send [b] print) [b] of A (foo 34) (bar 2) (woz 68) CLIPS> 9.3.3.4 Access FacetThere are three types of access facets which can be specified for a slot: read write, read only, and initialize only. The read write facet is the default and says that a slot can be both written and read. The read only facet says the slot can only be read; the only way to set this slot is with default facets in the class definition. The initialize only facet is like read only except that the slot can also be set by slot overrides in a make instance call(see section 9.6.1) and init message handlers (see section 9.4). These privileges apply to indirect access via messages as well as direct access within message handler bodies (see section 9.4). Note: a read only slot that has a static default value will implicitly have the shared storage facet. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (create-accessor write) (access read-write)) (slot bar (access read-only) (default abc)) (slot woz (create-accessor write) (access initialize-only))) CLIPS> (defmessage-handler A put-bar (?value) (dynamic-put (sym-cat bar) ?value)) CLIPS> (make-instance a of A (bar 34)) [MSGFUN3] bar slot in [a] of A: write access denied. [PRCCODE4] Execution halted during the actions of message-handler put-bar primary in class A FALSE CLIPS> (make-instance a of A (foo 34) (woz 65)) [a] CLIPS> (send [a] put-bar 1) [MSGFUN3] bar slot in [a] of A: write access denied. [PRCCODE4] Execution halted during the actions of message-handler put-bar primary in class A FALSE CLIPS> (send [a] put-woz 1) [MSGFUN3] woz slot in [a] of A: write access denied. [PRCCODE4] Execution halted during the actions of message-handler put-bar primary in class A FALSE CLIPS> (send [a] print) [a] of A (foo 34) (bar abc) (woz 65) CLIPS> 9.3.3.5 Inheritance Propagation FacetAn inherit facet says that a slot in a class can be given to instances of other classes that inherit from the first class. This is the default. The no inherit facet says that only direct instances of this class will get the slot. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (propagation inherit)) (slot bar (propagation no-inherit))) CLIPS> (defclass B (is-a A)) CLIPS> (make-instance a of A) [a] CLIPS> (make-instance b of B) [b] CLIPS> (send [a] print) [a] of A (foo nil) (bar nil) CLIPS> (send [b] print) [b] of B (foo nil) CLIPS> 9.3.3.6 Source FacetWhen obtaining slots from the class precedence list during instance creation, the default behavior is to take the facets from the most specific class which gives the slot and give default values to any unspecified facets. This is the behavior specified by the exclusive facet. The composite facet causes facets which are not explicitly specified by the most specific class to be taken from the next most specific class. Thus, in an overlay fashion, the facets of an instance’s slot can be specified by more than one class. Note that even though facets may be taken from superclasses, the slot is still considered to reside in the new class for purposes of visibility (see section 9.3.3.8). One good example of a use of this feature is to pick up a slot definition and change only its default value for a new derived class. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (multislot foo (access read-only) (default a b c))) CLIPS> (defclass B (is-a A) (slot foo (source composite) ; multiple and read-only ; from class A (default d e f))) CLIPS> (describe-class B) =============================================================== *************************************************************** Abstract: direct instances of this class cannot be created.
Inheritance Precedence: B A USER OBJECT Direct Subclasses: --------------------------------------------------------------- SLOTS : FLD DEF PRP ACC STO MCH SRC VIS CRT OVRD-MSG SOURCE(S) foo : MLT STC INH R LCL RCT CMP PRV NIL NIL A B
foo : + + + + + + + + RNG:[-oo..+oo] CRD:[0..+oo] --------------------------------------------------------------- Recognized message-handlers: init primary in class USER delete primary in class USER create primary in class USER print primary in class USER direct-modify primary in class USER message-modify primary in class USER direct-duplicate primary in class USER message-duplicate primary in class USER *************************************************************** =============================================================== CLIPS> 9.3.3.7 Pattern Match Reactivity FacetNormally, any change to a slot of an instance will be considered as a change to the instance for purposes of pattern matching. However, it is possible to indicate that changes to a slot of an instance should not cause pattern matching. The reactive facet specifies that changes to a slot trigger pattern matching, and this is the default. The non reactive facet specifies that changes to a slot do not affect pattern matching. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (pattern-match reactive) (slot foo (create-accessor write) (pattern-match non-reactive))) CLIPS> (defclass B (is-a USER) (role concrete) (pattern-match reactive) (slot foo (create-accessor write) (pattern-match reactive))) CLIPS> (defrule Create ?ins←(object (is-a A | B)) ⇒ (printout t “Create ” (instance-name ?ins) crlf)) CLIPS> (defrule Foo-Access ?ins←(object (is-a A | B) (foo ?)) ⇒ (printout t “Foo-Access ” (instance-name ?ins) crlf)) CLIPS> (make-instance a of A) [a] CLIPS> (make-instance b of B) [b] CLIPS> (run) Create [b] Foo-Access [b] Create [a] CLIPS> (send [a] put-foo 1) 1 CLIPS> (send [b] put-foo 1) 1 CLIPS> (run) Foo-Access [b] CLIPS> 9.3.3.8 Visibility FacetNormally, only message handlers attached to the class in which a slot is defined may directly access the slot. However, it is possible to allow message handlers attached to superclasses or subclasses which inherit the slot to directly access the slot as well. Declaring the visibility facet to be private specifies that only the message handlers of the defining class may directly access the slot, and this is the default. Declaring the visibility facet to be public specifies that the message handlers and subclasses which inherit the slot and superclasses may also directly access the slot. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot foo (visibility private))) CLIPS> (defclass B (is-a A) (role concrete)) CLIPS> (defmessage-handler B get-foo () ?self:foo) [MSGFUN6] Private slot foo of class A cannot be accessed directly by handlers attached to class B
(defmessage-handler MAIN::B get-foo () ?self:foo ) CLIPS> 9.3.3.9 Create Accessor FacetThe create accessor facet instructs CLIPS to automatically create explicit message handlers for reading and/or writing a slot. By default, implicit slot accessor message handlers are created for every slot. While these message handlers are real message handlers and can be manipulated as such, they have no pretty print form and cannot be directly modified by the user.
?self:<slot-name>)
(bind ?self:<slot-name> ?value)
(bind ?self:<slot-name> ?value)
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (create-accessor write)) (slot bar (create-accessor read)) CLIPS> (make-instance a of A (foo 36)) [a] CLIPS> (make-instance b of A (bar 45)) [MSGFUN1] No applicable primary message-handlers found for put-bar. FALSE CLIPS> 9.3.3.10 Override Message FacetThere are several COOL support functions which set slots via use of message passing, e.g., make instance, initialize instance, message modify instance and message duplicate instance. By default, all these functions attempt to set a slot with the message called put <slot name>. However, if the user has elected not to use standard slot accessors and wishes these functions to be able to perform slot overrides, then the override message facet can be used to indicate what message to send instead. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot special (override-message special-put))) CLIPS> (defmessage-handler A special-put primary (?value) (bind ?self:special ?value)) CLIPS> (watch messages) CLIPS> (make-instance a of A (special 65)) MSG » create ED:1 (<Instance-a>) MSG « create ED:1 (<Instance-a>) MSG » special-put ED:1 (<Instance-a> 65) MSG « special-put ED:1 (<Instance-a> 65) MSG » init ED:1 (<Instance-a>) MSG « init ED:1 (<Instance-a>) [a] CLIPS> (unwatch messages) CLIPS> 9.3.3.11 Constraint FacetsThe syntax and functionality of single and multifield constraint facets (attributes) are described in detail in Section 11. Static and dynamic constraint checking for classes and their instances is supported. Static checking is performed when constructs or commands which specify slot information are being parsed. Object patterns used on the LHS of a rule are also checked to determine if constraint conflicts exist among variables used in more that one slot. Errors for inappropriate values are immediately signaled. Static checking is enabled by default. This behavior can be changed using the set static constraint checking function. Dynamic checking is also supported. If dynamic checking is enabled, then new instances have their values checked whenever they are set (e.g. initialization, slot overrides, and put access). This dynamic checking is disabled by default. This behavior can be changed using the set dynamic constraint checking function. If an violation occurs when dynamic checking is being performed, then execution will be halted.
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (multislot foo (create-accessor write) (type SYMBOL) (cardinality 2 3))) CLIPS> (make-instance a of A (foo 45)) [a] CLIPS> (set-dynamic-constraint-checking TRUE) FALSE CLIPS> (make-instance a of A (foo red 5.0)) [CSTRNCHK1] (red 5.0) for slot foo of instance [a] found in put-foo primary in class A does not match the allowed types. [PRCCODE4] Execution halted during the actions of message-handler put-foo primary in class A FALSE CLIPS> (make-instance a of A (foo red)) [CSTRNCHK1] (red) for slot foo of instance [a] found in put-foo primary in class A does not satisfy the cardinality restrictions. [PRCCODE4] Execution halted during the actions of message-handler put-foo primary in class A FALSE CLIPS> 9.3.4 Message handler DocumentationCOOL allows the user to forward declare the message handlers for a class within the defclass statement. These declarations are for documentation only and are ignored by CLIPS. The defmessage handler construct must be used to actually add message handlers to a class. Message handlers can later be added which are not documented in the defclass. Example CLIPS> (clear) CLIPS> (defclass rectangle (is-a USER) (slot side-a (default 1)) (slot side-b (default 1)) (message-handler find-area)) CLIPS> (defmessage-handler rectangle find-area () (* ?self:side-a ?self:side-b)) CLIPS> (defmessage-handler rectangle print-area () (printout t (send ?self find-area) crlf)) CLIPS> 9.4 Defmessage handler ConstructObjects are manipulated by sending them messages via the function send. The result of a message is a useful return value or side effect. A defmessage handler is a construct for specifying the behavior of a class of objects in response to a particular message. The implementation of a message is made up of pieces of procedural code called message handlers (or handlers for short). Each class in the class precedence list of an object’s class can have handlers for a message. In this way, the object’s class and all its superclasses share the labor of handling the message. Each class’s handlers handle the part of the message which is appropriate to that class. Within a class, the handlers for a particular message can be further subdivided into four types or categories: primary, before, after and around. The intended purposes of each type are summarized in the chart below:
Syntax Defaults are outlined.
[<handler-type>] [<comment>] (<parameter>* [<wildcard-parameter>]) <action>*)
<parameter> ::= <single-field-variable> <wildcard-parameter> ::= <multifield-variable>
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete)) CLIPS> (defmessage-handler A delete before () (printout t “Deleting an instance of the class A…” crlf)) CLIPS> (defmessage-handler USER delete after () (printout t “System completed deletion of an instance.” crlf)) CLIPS> (watch instances) CLIPS> (make-instance a of A) ==> instance [a] of A [a] CLIPS> (send [a] delete) Deleting an instance of the class A… ⇐= instance [a] of A System completed deletion of an instance. TRUE CLIPS> (unwatch instances) CLIPS> 9.4.1 Message handler ParametersA message handler may accept exactly or at least a specified number of arguments, depending on whether a wildcard parameter is used or not. The regular parameters specify the minimum number of arguments that must be passed to the handler. Each of these parameters may be referenced like a normal single field variable within the actions of the handler. If a wildcard parameter is present, the handler may be passed any number of arguments greater than or equal to the minimum. If no wildcard parameter is present, then the handler must be passed exactly the number of arguments specified by the regular parameters. All arguments to a handler that do not correspond to a regular parameter are grouped into a multifield value that can be referenced by the wildcard parameter. The standard CLIPS multifield functions, such as length$ and expand$, can be applied to the wildcard parameter.
Example CLIPS> (clear) CLIPS> (defclass CAR (is-a USER) (role concrete) (slot front-seat) (multislot trunk) (slot trunk-count)) CLIPS> (defmessage-handler CAR put-items-in-car (?item $?rest) (bind ?self:front-seat ?item) (bind ?self:trunk ?rest) (bind ?self:trunk-count (length$ ?rest))) CLIPS> (make-instance Pinto of CAR) [Pinto] CLIPS> (send [Pinto] put-items-in-car bag-of-groceries tire suitcase) 2 CLIPS> (send [Pinto] print) [Pinto] of CAR (front-seat bag-of-groceries) (trunk tire suitcase) (trunk-count 2) CLIPS> 9.4.1.1 Active Instance ParameterThe term active instance refers to an instance which is responding to a message. All message handlers have an implicit parameter called ?self which binds the active instance for a message. This parameter name is reserved and cannot be explicitly listed in the message handler’s parameters, nor can it be rebound within the body of a message handler. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete)) CLIPS> (make-instance a of A) [a] CLIPS> (defmessage-handler A print-args (?a ?b $?c) (printout t (instance-name ?self) ” “ ?a ” “ ?b ” and “ (length$ ?c) ” extras: “ ?c crlf)) CLIPS> (send [a] print-args 1 2) [a] 1 2 and 0 extras: () CLIPS> (send [a] print-args a b c d) [a] a b and 2 extras: (c d) CLIPS> 9.4.2 Message handler ActionsThe body of a message handler is a sequence of expressions that are executed in order when the handler is called. The return value of the message handler is the result of the evaluation of the last expression in the body.
Syntax ?self:<slot-name> Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (default 1)) (slot bar (default 2))) CLIPS> (defmessage-handler A print-all-slots () (printout t ?self:foo ” “ ?self:bar crlf)) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] print-all-slots) 1 2 CLIPS>
Syntax (bind ?self:<slot-name> <value>*) Example CLIPS> (defmessage-handler A set-foo (?value) (bind ?self:foo ?value)) CLIPS> (send [a] set-foo 34) 34 CLIPS>
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot foo (create-accessor read))) CLIPS> (defclass B (is-a A) (role concrete) (slot foo)) CLIPS> (make-instance b of B) [b] CLIPS> (send [b] get-foo) [MSGPASS3] Static reference to slot foo of class A does not apply to [b] of B [PRCCODE4] Execution halted during the actions of message-handler get-foo primary in class A FALSE CLIPS>
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot foo)) CLIPS> (defmessage-handler A get-foo () (dynamic-get foo)) CLIPS> (defclass B (is-a A) (role concrete) (slot foo (visibility public))) CLIPS> (make-instance b of B) [b] CLIPS> (send [b] get-foo) nil CLIPS> 9.4.3 DaemonsDaemons are pieces of code which execute implicitly whenever some basic action is taken upon an instance, such as initialization, deletion, or reading and writing of slots. All these basic actions are implemented with primary handlers attached to the class of the instance. Daemons may be easily implemented by defining other types of message handlers, such as before or after, which will recognize the same messages. These pieces of code will then be executed whenever the basic actions are performed on the instance. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete)) CLIPS> (defmessage-handler A init before () (printout t “Initializing a new instance of class A…” crlf)) CLIPS> (make-instance a of A) Initializing a new instance of class A… [a] CLIPS> 9.4.4 Predefined System Message handlersCLIPS defines eight primary message handlers that are attached to the class USER. These handlers cannot be deleted or modified. 9.4.4.1 Instance InitializationSyntax (defmessage-handler USER init primary ())
Example CLIPS> (clear) CLIPS> (defclass CAR (is-a USER) (role concrete) (slot price (default 75000)) (slot model (default Corniche))) CLIPS> (watch messages) CLIPS> (watch message-handlers) CLIPS> (make-instance Rolls-Royce of CAR) MSG » create ED:1 (<Instance-Rolls-Royce>) HND » create primary in class USER ED:1 (<Instance-Rolls-Royce>) HND « create primary in class USER ED:1 (<Instance-Rolls-Royce>) MSG « create ED:1 (<Instance-Rolls-Royce>) MSG » init ED:1 (<Instance-Rolls-Royce>) HND » init primary in class USER ED:1 (<Instance-Rolls-Royce>) HND « init primary in class USER ED:1 (<Instance-Rolls-Royce>) MSG « init ED:1 (<Instance-Rolls-Royce>) [Rolls-Royce] CLIPS> 9.4.4.2 Instance DeletionSyntax (defmessage-handler USER delete primary ())
Example CLIPS> (send [Rolls-Royce] delete) MSG » delete ED:1 (<Instance-Rolls-Royce>) HND » delete primary in class USER ED:1 (<Instance-Rolls-Royce>) HND « delete primary in class USER ED:1 (<Stale Instance-Rolls-Royce>) MSG « delete ED:1 (<Stale Instance-Rolls-Royce>) TRUE CLIPS> 9.4.4.3 Instance DisplaySyntax (defmessage-handler USER print primary ())
Example CLIPS> (make-instance Rolls-Royce of CAR) MSG » create ED:1 (<Instance-Rolls-Royce>) HND » create primary in class USER ED:1 (<Instance-Rolls-Royce>) HND « create primary in class USER ED:1 (<Instance-Rolls-Royce>) MSG « create ED:1 (<Instance-Rolls-Royce>) MSG » init ED:1 (<Instance-Rolls-Royce>) HND » init primary in class USER ED:1 (<Instance-Rolls-Royce>) HND « init primary in class USER ED:1 (<Instance-Rolls-Royce>) MSG « init ED:1 (<Instance-Rolls-Royce>) [Rolls-Royce] CLIPS> (send [Rolls-Royce] print) MSG » print ED:1 (<Instance-Rolls-Royce>) HND » print primary in class USER ED:1 (<Instance-Rolls-Royce>) [Rolls-Royce] of CAR (price 75000) (model Corniche) HND « print primary in class USER ED:1 (<Instance-Rolls-Royce>) MSG « print ED:1 (<Instance-Rolls-Royce>) CLIPS> (unwatch messages) CLIPS. (unwatch message-handlers) CLIPS> 9.4.4.4 Directly Modifying an InstanceSyntax (defmessage-handler USER direct-modify primary (?slot-override-expressions))
Example The following around message handler could be used to insure that all modify message slot overrides are handled using put- messages.
(?overrides) (send ?self message-modify ?overrides)) 9.4.4.5 Modifying an Instance using MessagesSyntax (defmessage-handler USER message-modify primary (?slot-override-expressions)
9.4.4.6 Directly Duplicating an InstanceSyntax (defmessage-handler USER direct-duplicate primary (?new-instance-name ?slot-override-expressions))
Example The following around message handler could be used to insure that all duplicate message slot overrides are handled using put- messages.
(?new-name ?overrides) (send ?self message-duplicate ?new-name ?overrides)) 9.4.4.7 Duplicating an Instance using MessagesSyntax (defmessage-handler USER message-duplicate primary (?new-instance-name ?slot-override-expressions)
9.4.4.8 Instance CreationSyntax (defmessage-handler USER create primary ())
9.5 Message DispatchWhen a message is sent to an object using the send function, CLIPS examines the class precedence list of the active instance’s class to determine a complete set of message handlers which are applicable to the message. CLIPS uses the roles (around, before, primary or after) and specificity of these message handlers to establish an ordering and then executes them. A handler which is attached to a subclass of another message handler’s class is said to be more specific. This entire process is referred to as the message dispatch. Following is a flow diagram summary:
9.5.1 Applicability of Message handlersA message handler is applicable to a message if its name matches the message, and it is attached to a class which is in the class precedence list of the class of the instance receiving the message. 9.5.2 Message handler PrecedenceThe set of all applicable message handlers are sorted into four groups according to role, and these four groups are further sorted by class specificity. The around, before and primary handlers are ordered from most specific to most general, whereas after handlers are ordered from most general to most specific.
9.5.3 Shadowed Message handlersWhen one handler must be called by another handler in order to be executed, the first handler is said to be shadowed by the second. An around handler shadows all handlers except more specific around handlers. A primary handler shadows all more general primary handlers.
Example 9.5.4 Message Execution ErrorsIf an error occurs at any time during the execution of a message handler, any currently executing handlers will be aborted, any handlers which have not yet started execution will be ignored, and the sendfunction will return the symbol FALSE.
9.5.5 Message Return ValueThe return value of call to the send function is the return value of the most specific around handler, or the most specific primary handler if there are no around handlers. The return value of a handler is the result of the evaluation of the last action in the handler.
9.6 Manipulating InstancesObjects are manipulated by sending them messages. This is achieved by using the send function, which takes as arguments the destination object for the message, the message itself and any arguments which are to be passed to handlers. Syntax (send <object-expression> <message-name-expression> <expression>*)
9.6.1 Creating InstancesLike facts, instances of user defined classes must be explicitly created by the user. Likewise, all instances are deleted during the resetcommand, and they can be loaded and saved similarly to facts. All operations involving instances require message passing using the send function except for creation, since the object does not yet exist. A function called make instance is used to create and initialize a new instance. This function implicitly sends first a create message and then an initialization message to the new object after allocation. The user can customize instance initialization with daemons. make instance also allows slot overrides to change any predefined initialization for a particular instance. make instance automatically delays all object pattern matching activities for rules until all slot overrides have been processed. The function active make instance can be used if delayed pattern matching is not desired. active make instance remembers the current state of delayed pattern matching, explicitly turns delay on, and then restores it to its previous state once all slot overrides have been processed. Syntax (make-instance <instance-definition>) (active-make-instance <instance-definition>)
<class-name-expression> <slot-override>* <slot-override> ::= (<slot-name-expression> <expression>*)
2) A new and uninitialized instance of the specified class is created with the specified name. 3) The new instance receives the create message, e.g. (send <instance name> create). Normally, the handler attached to class USER will respond to this message (see section 9.4.4.8), although it performs no actions. 4) All slot overrides are immediately evaluated and placed via put messages (see section 9.3.3.10), e.g. (send <instance name> put <slot name> <expression>*). If there are any errors, the new instance is deleted. 5) The new instance receives the init message, e.g. (send <instance name> init). Normally, the handler attached to class USER will respond to this message (see section 9.4.4.1). This handler calls the init slots function (see section 12.16.4.1). This function uses defaults from the class definition (if any) for any slots which do not have slot overrides. The class defaults are placed directly without the use of messages. If there are any errors, the new instance is deleted. Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot x (default 34) (create-accessor write)) (slot y (default abc))) CLIPS> (defmessage-handler A put-x before (?value) (printout t “Slot x set with message.” crlf)) CLIPS> (defmessage-handler A delete after () (printout t “Old instance deleted.” crlf)) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] print) [a] of A (x 34) (y abc) CLIPS> (make-instance [a] of A (x 65)) Old instance deleted. Slot x set with message. [a] CLIPS> (send [a] print) a of A (x 65) (y abc) CLIPS> (send [a] delete) Old instance deleted. TRUE CLIPS> 9.6.1.1 Definstances ConstructSimilar to deffacts, the definstances construct allows the specification of instances which will be created every time the reset command is executed. On every reset all current instances receive a delete message, and the equivalent of a make instancefunction call is made for every instance specified in definstances constructs. Syntax (definstances <definstances-name> [active] [<comment>] <instance-template>*) <instance-template> ::= (<instance-definition>)
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot x (create-accessor write) (default 1))) CLIPS> (definstances A-OBJECTS (a1 of A) (of A (x 65))) CLIPS> (watch instances) CLIPS> (reset) ==> instance [initial-object] of INITIAL-OBJECT ==> instance [a1] of A ==> instance [gen1] of A CLIPS> (reset) ⇐= instance [initial-object] of INITIAL-OBJECT ⇐= instance [a1] of A ⇐= instance [gen1] of A ==> instance [initial-object] of INITIAL-OBJECT ==> instance [a1] of A ==> instance [gen2] of A CLIPS> (unwatch instances) CLIPS>
(initial-object of INITIAL-OBJECT))
(is-a USER) (role concrete) (pattern-match reactive))
9.6.2 Reinitializing Existing InstancesThe initialize instance function provides the ability to reinitialize an existing instance with class defaults and new slot overrides. The return value of initialize instance is the name of the instance on success or the symbol FALSE on failure. The evaluation of <instance name expression> can either be an instance name, instance address or a symbol. initialize instance automatically delays all object pattern matching activities for rules until all slot overrides have been processed. The function active initialize instance can be used if delayed pattern matching is not desired. Syntax (initialize-instance <instance-name-expression> <slot-override>*)
2) The instance receives the init message, e.g. (send <instance name> init). Normally, the handler attached to class USER will respond to this message (see section 9.4.5.1). This handler calls the init slots function (see section 12.16.4.1). This function uses defaults from the class definition (if any) for any slots which do not have slot overrides. The class defaults are placed directly without the use of messages.
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot x (default 34) (create-accessor write)) (slot y (default ?NONE) (create-accessor write)) (slot z (create-accessor write))) CLIPS> (make-instance a of A (y 100)) [a] CLIPS> (send [a] print) [a] of A (x 34) (y 100) (z nil) CLIPS> (send [a] put-x 65) 65 CLIPS> (send [a] put-y abc) abc CLIPS> (send [a] put-z “Hello world.”) “Hello world.” CLIPS> (send [a] print) [a] of A (x 65) (y abc) (z “Hello world.”) CLIPS> (initialize-instance a) [a] CLIPS> (send [a] print) a of A (x 34) (y abc) (z nil) CLIPS> 9.6.3 Reading SlotsSources external to an object, such as a rule or deffunction, can read an object’s slots only by sending the object a message. Message handlers executing on the behalf of an object can either use messages or direct access to read the object’s slots (see section 9.4.2). Several functions also exist which operate implicitly on the active instance for a message that can only be called by message handlers, such as dynamic get (see section 12.16.4.10).
Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot x (create-accessor read) (default abc))) CLIPS> (make-instance a of A) [a] CLIPS> (sym-cat (send [a] get-x) def) abcdef CLIPS> 9.6.4 Setting SlotsSources external to an object, such as a rule or deffunction, can write an object’s slots only by sending the object a message. Several functions also exist which operate implicitly on the active instance for a message that can only be called by message handlers, such as dynamic put (see section 12.16.4.11). The bind function can also be used to set a slot's value from within a message handler (see section 9.4.2). Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot x (create-accessor write) (default abc))) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] put-x “New value.”) “New value.” CLIPS> 9.6.5 Deleting InstancesSending the delete message to an instance removes it from the system. Within a message handler, the delete instance function (see section 12.16) can be used to delete the active instance for a message. Syntax (send <instance> delete) 9.6.6 Delayed Pattern Matching When Manipulating InstancesWhile manipulating instances (either by creating, modifying, or deleting), it is possible to delay pattern matching activities for rules until after all of the manipulations have been made. This can be accomplished using the object pattern match delay function. This function acts identically to the progn function, however, any actions which could affect object pattern matching for rules are delayed until the function is exited. This function’s primary purpose is to provide some control over performance. Syntax (object-pattern-match-delay <action>*) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (pattern-match reactive)) CLIPS> (defrule match-A (object (is-a A)) ⇒) CLIPS> (make-instance a of A) [a] CLIPS> (agenda) 0 match-A: [a] For a total of 1 activation. CLIPS> (make-instance b of A) [b] CLIPS> (agenda) 0 match-A: [b] 0 match-A: [a] For a total of 2 activations. CLIPS> (object-pattern-match-delay (make-instance c of A) (printout t “After c…” crlf) (agenda) (make-instance d of A) (printout t “After d…” crlf) (agenda)) After c… 0 match-A: [b] 0 match-A: [a] For a total of 2 activations. After d… 0 match-A: [b] 0 match-A: [a] For a total of 2 activations. CLIPS> (agenda) 0 match-A: [d] 0 match-A: [c] 0 match-A: [b] 0 match-A: [a] For a total of 4 activations. CLIPS> 9.6.7 Modifying InstancesFour functions are provided for modifying instances. These functions allow instance slot updates to be performed in blocks without requiring a series of put messages. Each of these functions returns the symbol TRUE if successful, otherwise the symbol FALSE is returned. 9.6.7.1 Directly Modifying an Instance with Delayed Pattern MatchingThe modify instance function uses the direct modify message to change the values of the instance. Object pattern matching is delayed until all of the slot modifications have been performed. Syntax (modify-instance <instance> <slot-override>*) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo) (slot bar)) CLIPS> (make-instance a of A) [a] CLIPS> (watch all) CLIPS> (modify-instance a (foo 0)) MSG » direct-modify ED:1 (<Instance-a> <Pointer-0019CD5A>) HND » direct-modify primary in class USER. ED:1 (<Instance-a> <Pointer-0019CD5A>) ::= local slot foo in instance a ← 0 HND « direct-modify primary in class USER. ED:1 (<Instance-a> <Pointer-0019CD5A>) MSG « direct-modify ED:1 (<Instance-a> <Pointer-0019CD5A>) TRUE CLIPS> (unwatch all) CLIPS> 9.6.7.2 Directly Modifying an Instance with Immediate Pattern MatchingThe active modify instance function uses the direct modify message to change the values of the instance. Object pattern matching occurs as slot modifications are being performed. Syntax (active-modify-instance <instance> <slot-override>*) 9.6.7.3 Modifying an Instance using Messages with Delayed Pattern MatchingThe message modify instance function uses the message modify message to change the values of the instance. Object pattern matching is delayed until all of the slot modifications have been performed. Syntax (message-modify-instance <instance> <slot-override>*) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo) (slot bar (create-accessor write))) CLIPS> (make-instance a of A) [a] CLIPS> (watch all) CLIPS> (message-modify-instance a (bar 4)) MSG » message-modify ED:1 (<Instance-a> <Pointer-009F04A0>) HND » message-modify primary in class USER ED:1 (<Instance-a> <Pointer-009F04A0>) MSG » put-bar ED:2 (<Instance-a> 4) HND » put-bar primary in class A ED:2 (<Instance-a> 4) ::= local slot bar in instance a ← 4 HND « put-bar primary in class A ED:2 (<Instance-a> 4) MSG « put-bar ED:2 (<Instance-a> 4) HND « message-modify primary in class USER ED:1 (<Instance-a> <Pointer-009F04A0>) MSG « message-modify ED:1 (<Instance-a> <Pointer-009F04A0>) TRUE CLIPS> (unwatch all) CLIPS> 9.6.7.4 Modifying an Instance using Messages with Immediate Pattern MatchingThe active message modify instance function uses the message modify message to change the values of the instance. Object pattern matching occurs as slot modifications are being performed. Syntax (active-message-modify-instance <instance> <slot-override>*) 9.6.8 Duplicating InstancesFour functions are provided for duplicating instances. These functions allow instance duplication and slot updates to be performed in blocks without requiring a series of put messages. Each of these functions return the instance name of the new duplicated instance if successful, otherwise the symbol FALSE is returned.
9.6.8.1 Directly Duplicating an Instance with Delayed Pattern MatchingThe duplicate instance function uses the direct duplicate message to change the values of the instance. Object pattern matching is delayed until all of the slot modifications have been performed. Syntax (duplicate-instance <instance> [to <instance name>] <slot-override>*) Example CLIPS> (clear) CLIPS> (setgen 1) 1 CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (create-accessor write)) (slot bar (create-accessor write))) CLIPS> (make-instance a of A (foo 0) (bar 4)) [a] CLIPS> (watch all) CLIPS> (duplicate-instance a) MSG » direct-duplicate ED:1 (<Instance-a> [gen1] <Pointer-00000000>) HND » direct-duplicate primary in class USER ED:1 (<Instance-a> [gen1] <Pointer-00000000>) ==> instance [gen1] of A ::= local slot foo in instance gen1 ← 0 ::= local slot bar in instance gen1 ← 4 HND « direct-duplicate primary in class USER ED:1 (<Instance-a> [gen1] <Pointer-00000000>) MSG « direct-duplicate ED:1 (<Instance-a> [gen1] <Pointer-00000000>) [gen1] CLIPS> (unwatch all) CLIPS> 9.6.8.2 Directly Duplicating an Instance with Immediate Pattern MatchingThe active duplicate instance function uses the direct duplicate message to change the values of the instance. Object pattern matching occurs as slot modifications are being performed. Syntax (active-duplicate-instance <instance> [to <instance name>] <slot-override>*) 9.6.8.3 Duplicating an Instance using Messages with Delayed Pattern MatchingThe message duplicate instance function uses the message duplicate message to change the values of the instance. Object pattern matching is delayed until all of the slot modifications have been performed. Syntax (message-duplicate-instance <instance> [to <instance name>] <slot-override>*) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete) (slot foo (create-accessor write)) (slot bar (create-accessor write))) CLIPS> (make-instance a of A (foo 0) (bar 4)) [a] CLIPS> (make-instance b of A) [b] CLIPS> (watch all) CLIPS> (message-duplicate-instance a to b (bar 6)) MSG » message-duplicate ED:1 (<Instance-a> [b] <Pointer-009F04A0>) HND » message-duplicate primary in class USER ED:1 (<Instance-a> [b] <Pointer-009F04A0>) MSG » delete ED:2 (<Instance-b>) HND » delete primary in class USER ED:2 (<Instance-b>) ⇐= instance [b] of A HND « delete primary in class USER ED:2 (<Stale Instance-b>) MSG « delete ED:2 (<Stale Instance-b>) ==> instance [b] of A MSG » create ED:2 (<Instance-b>) HND » create primary in class USER ED:2 (<Instance-b>) HND « create primary in class USER ED:2 (<Instance-b>) MSG « create ED:2 (<Instance-b>) MSG » put-bar ED:2 (<Instance-b> 6) HND » put-bar primary in class A ED:2 (<Instance-b> 6) ::= local slot bar in instance b ← 6 HND « put-bar primary in class A ED:2 (<Instance-b> 6) MSG « put-bar ED:2 (<Instance-b> 6) MSG » put-foo ED:2 (<Instance-b> 0) HND » put-foo primary in class A ED:2 (<Instance-b> 0) ::= local slot foo in instance b ← 0 HND « put-foo primary in class A ED:2 (<Instance-b> 0) MSG « put-foo ED:2 (<Instance-b> 0) MSG » init ED:2 (<Instance-b>) HND » init primary in class USER ED:2 (<Instance-b>) HND « init primary in class USER ED:2 (<Instance-b>) MSG « init ED:2 (<Instance-b>) HND « message-duplicate primary in class USER ED:1 (<Instance-a> [b] <Pointer-009F04A0>) MSG « message-duplicate ED:1 (<Instance-a> [b] <Pointer-009F04A0>) [b] CLIPS> (unwatch all) CLIPS> 9.6.8.4 Duplicating an Instance using Messages with Immediate Pattern MatchingThe active message duplicate instance function uses the message duplicate message to change the values of the instance. Object pattern matching occurs as slot modifications are being performed. Syntax (active-message-duplicate-instance <instance> [to <instance name>] <slot-override>*)
9.7 Instance set Queries and Distributed ActionsCOOL provides a useful query system for determining and performing actions on sets of instances of user defined classes that satisfy user defined queries. The instance query system in COOL provides six functions, each of which operate on instance sets determined by user defined criteria:
Example
Example CLIPS> (defclass PERSON (is-a USER) (role abstract) (slot sex (access read-only) (storage shared)) (slot age (type NUMBER) (visibility public))) CLIPS> (defmessage-handler PERSON put-age (?value) (dynamic-put age ?value)) CLIPS> (defclass FEMALE (is-a PERSON) (role abstract) (slot sex (source composite) (default female))) CLIPS> (defclass MALE (is-a PERSON) (role abstract) (slot sex (source composite) (default male))) CLIPS> (defclass GIRL (is-a FEMALE) (role concrete) (slot age (source composite) (default 4) (range 0.0 17.9))) CLIPS> (defclass WOMAN (is-a FEMALE) (role concrete) (slot age (source composite) (default 25) (range 18.0 100.0))) CLIPS> (defclass BOY (is-a MALE) (role concrete) (slot age (source composite) (default 4) (range 0.0 17.9))) CLIPS> (defclass MAN (is-a MALE) (role concrete) (slot age (source composite) (default 25) (range 18.0 100.0))) CLIPS> (definstances PEOPLE (Man-1 of MAN (age 18)) (Man-2 of MAN (age 60)) (Woman-1 of WOMAN (age 18)) (Woman-2 of WOMAN (age 60)) (Woman-3 of WOMAN) (Boy-1 of BOY (age 8)) (Boy-2 of BOY) (Boy-3 of BOY) (Boy-4 of BOY) (Girl-1 of GIRL (age 8)) (Girl-2 of GIRL)) CLIPS> (reset) CLIPS> 9.7.1 Instance set DefinitionAn instance set is an ordered collection of instances. Each instance set member is an instance of a set of classes, called class restrictions, defined by the user. The class restrictions can be different for each instance set member. The query functions use instance set templates to generate instance sets. An instance set template is a set of instance set member variables and their associated class restrictions. Instance set member variables reference the corresponding members in each instance set which matches a template. Variables may be used to specify the classes for the instance set template, but if the constant names of the classes are specified, the classes must already be defined. Module specifiers may be included with the class names; the classes need not be in scope of the current module. Syntax <instance-set-template> ::= (<instance-set-member-template>+) <instance-set-member-template> ::= (<instance-set-member-variable> <class-restrictions>) <instance-set-member-variable> ::= <single-field-variable> <class-restrictions> ::= <class-name-expression>+ Example One instance set template might be the ordered pairs of boys or men and girls or women.
9.7.2 Instance set DeterminationCOOL uses straightforward permutations to generate instance sets that match an instance set template from the actual instances in the system. The rules are as follows:
2) When there is more than one class that an instance set member can be, iterate through the classes from left to right. 3) Examine instances of a class in the order that they were defined. 3a) Recursively examine instances of subclasses in the order that the subclasses were defined. If the specified query class was in scope of the current module, then only subclasses which are also in scope will be examined. Otherwise, only subclasses which are in scope of the module to which the query class belongs will be examined. Example For the instance set template given in section 9.7.1, thirty instance sets would be generated in the following order:
Example Consider the following instance set template:
9.7.3 Query DefinitionA query is a user defined boolean expression applied to an instance set to determine if the instance set meets further user defined restrictions. If the evaluation of this expression for an instance set is anything but the symbol FALSE, the instance set is said to satisfy the query. Syntax <query> ::= <boolean-expression> Example Continuing the previous example, one query might be that the two instances in an ordered pair have the same age.
Syntax <instance-set-member-variable>:<slot-name> Example The previous example could be rewritten as:
9.7.4 Distributed Action DefinitionA distributed action is a user defined expression evaluated for each instance set which satisfies a query. Unlike queries, distributed actions must use messages to read slots of instance set members. If more than one action is required, use the progn function (see section 12.6.5) to group them. Action Syntax <action> ::= <expression> Example Continuing the previous example, one distributed action might be to simply print out the ordered pair to the screen.
9.7.5 Scope in Instance set Query FunctionsAn instance set query function can be called from anywhere that a regular function can be called. If a variable from an outer scope is not masked by an instance set member variable, then that variable may be referenced within the query and action. In addition, rebinding variables within an instance set function action is allowed. However, attempts to rebind instance set member variables will generate errors. Binding variables is not allowed within a query. Instance set query functions can be nested. Example CLIPS> (deffunction count-instances (?class) (bind ?count 0) (do-for-all-instances ((?ins ?class)) TRUE (bind ?count (+ ?count 1))) ?count) CLIPS> (deffunction count-instances-2 (?class) (length (find-all-instances ((?ins ?class)) TRUE))) CLIPS> (count-instances WOMAN) 3 CLIPS> (count-instances-2 BOY) 4 CLIPS>
Example CLIPS> (deffunction last-instance (?class) (any-instancep ((?ins ?class)) TRUE) ?ins)
(deffunction last-instance (?class) (any-instancep ((?ins ?class)) TRUE) ?ins ) CLIPS> 9.7.6 Errors during Instance set Query FunctionsIf an error occurs during an instance set query function, the function will be immediately terminated and the return value will be the symbol FALSE. 9.7.7 Halting and Returning Values from Query FunctionsThe functions break and return are now valid inside the action of the instance set query functions do for instance, do for all instances and delayed do for all instances. The return function is only valid if it is applicable in the outer scope, whereas the break function actually halts the query. 9.7.8 Instance set Query FunctionsThe instance query system in COOL provides six functions. For a given set of instances, all six query functions will iterate over these instances in the same order (see section 9.7.2). However, if a particular instance is deleted and recreated, the iteration order will change. 9.7.8.1 Testing if Any Instance set Satisfies a QueryThis function applies a query to each instance set which matches the template. If an instance set satisfies the query, then the function is immediately terminated, and the return value is the symbol TRUE. Otherwise, the return value is the symbol FALSE. Syntax (any instancep <instance-set-template> <query>) Example Are there any men over age 30?
TRUE CLIPS> 9.7.8.2 Determining the First Instance set Satisfying a QueryThis function applies a query to each instance set which matches the template. If an instance set satisfies the query, then the function is immediately terminated, and the instance set is returned in a multifield value. Otherwise, the return value is a zero length multifield value. Each field of the multifield value is an instance name representing an instance set member. Syntax (find instance <instance-set-template> <query>) Example Find the first pair of a man and a woman who have the same age.
(find-instance ((?m MAN) (?w WOMAN)) (= ?m:age ?w:age)) ([Man-1] [Woman-1]) CLIPS> 9.7.8.3 Determining All Instance sets Satisfying a QueryThis function applies a query to each instance set which matches the template. Each instance set which satisfies the query is stored in a multifield value. This multifield value is returned when the query has been applied to all possible instance sets. If there are n instances in each instance set, and m instance sets satisfied the query, then the length of the returned multifield value will be n * m. The first n fields correspond to the first instance set, and so on. Each field of the multifield value is an instance name representing an instance set member. The multifield value can consume a large amount of memory due to permutational explosion, so this function should be used judiciously. Syntax (find all instances <instance-set-template> <query>) Example Find all pairs of a man and a woman who have the same age.
(find-all-instances ((?m MAN) (?w WOMAN)) (= ?m:age ?w:age)) ([Man-1] [Woman-1] [Man-2] [Woman-2]) CLIPS> 9.7.8.4 Executing an Action for the First Instance set Satisfying a QueryThis function applies a query to each instance set which matches the template. If an instance set satisfies the query, the specified action is executed, and the function is immediately terminated. The return value is the evaluation of the action. If no instance set satisfied the query, then the return value is the symbol FALSE. Syntax (do for instance <instance-set-template> <query> <action>*) Example Print out the first triplet of different people that have the same age. The calls to neq in the query eliminate the permutations where two or more members of the instance set are identical.
(do-for-instance ((?p1 PERSON) (?p2 PERSON) (?p3 PERSON)) (and (= ?p1:age ?p2:age ?p3:age) (neq ?p1 ?p2) (neq ?p1 ?p3) (neq ?p2 ?p3)) (printout t ?p1 ” “ ?p2 ” “ ?p3 crlf)) [Girl-2] [Boy-2] [Boy-3] CLIPS> 9.7.8.5 Executing an Action for All Instance sets Satisfying a QueryThis function applies a query to each instance set which matches the template. If an instance set satisfies the query, the specified action is executed. The return value is the evaluation of the action for the last instance set which satisfied the query. If no instance set satisfied the query, then the return value is the symbol FALSE. Syntax (do for all instances <instance-set-template> <query> <action>*) Example Print out all triplets of different people that have the same age. The calls to str compare limit the instance sets which satisfy the query to combinations instead of permutations. Without these restrictions, two instance sets which differed only in the order of their members would both satisfy the query.
(do-for-all-instances ((?p1 PERSON) (?p2 PERSON) (?p3 PERSON)) (and (= ?p1:age ?p2:age ?p3:age) (> (str-compare ?p1 ?p2) 0) (> (str-compare ?p2 ?p3) 0)) (printout t ?p1 ” “ ?p2 ” “ ?p3 crlf)) [Girl-2] [Boy-3] [Boy-2] [Girl-2] [Boy-4] [Boy-2] [Girl-2] [Boy-4] [Boy-3] [Boy-4] [Boy-3] [Boy-2] CLIPS> 9.7.8.6 Executing a Delayed Action for All Instance setsSatisfying a QueryThis function is similar to do for all instances except that it groups all instance sets which satisfy the query into an intermediary multifield value. If there are no instance sets which satisfy the query, then the function returns the symbol FALSE. Otherwise, the specified action is executed for each instance set in the multifield value, and the return value is the evaluation of the action for the last instance set to satisfy the query. The intermediary multifield value is discarded. This function can consume large amounts of memory in the same fashion as find all instances. This function should be used in lieu of do for all instances when the action applied to one instance set would change the result of the query for another instance set (unless that is the desired effect). Syntax (delayed do for all instances <instance-set-template> <query> <action>*) Example Delete all boys with the greatest age. The test in this case is another query function which determines if there are any older boys than the one currently being examined. The action needs to be delayed until all boys have been processed, or the greatest age will decrease as the older boys are deleted.
CLIPS> (delayed-do-for-all-instances ((?b1 BOY)) (not (any-instancep ((?b2 BOY)) (> ?b2:age ?b1:age))) (send ?b1 delete)) ⇐= instance [Boy-1] of BOY TRUE CLIPS> (unwatch instances) CLIPS> (reset) CLIPS> (watch instances) CLIPS> (do-for-all-instances ((?b1 BOY)) (not (any-instancep ((?b2 BOY)) (> ?b2:age ?b1:age))) (send ?b1 delete)) ⇐= instance [Boy-1] of BOY ⇐= instance [Boy-2] of BOY ⇐= instance [Boy-3] of BOY ⇐= instance [Boy-4] of BOY TRUE CLIPS> (unwatch instances) CLIPS> Section 10 Defmodule ConstructCLIPS provides support for the modular development and execution of knowledge bases with the defmodule construct. CLIPS modules allow a set of constructs to be grouped together such that explicit control can be maintained over restricting the access of the constructs by other modules. This type of control is similar to global and local scoping used in languages such as C or Ada (note, however, that the global scoping used by CLIPS is strictly hierarchical and in one direction only—if module A can see constructs from module B, then it is not possible for module B to see any of module A’s constructs). By restricting access to deftemplate and defclass constructs, modules can function as blackboards, permitting only certain facts and instances to be seen by other modules. Modules are also used by rules to provide execution control. 10.1 Defining ModulesModules are defined using the defmodule construct. Syntax (defmodule <module-name> [<comment>] <port-spec>*)
(import <module-name> <port-item>) <port-item> ::= ?ALL | ?NONE | <port-construct> ?ALL | <port-construct> ?NONE | <port-construct> <construct-name>+
defglobal | deffunction | defgeneric
(defmodule FOO (import BAR ?ALL) (import YAK deftemplate ?ALL) (import GOZ defglobal x y z) (export defgeneric +) (export defclass ?ALL)) 10.2 Specifying a Construct’s ModuleThe module in which a constructs is placed can be specified when the construct is defined. The deffacts, deftemplate, defrule, deffunction, defgeneric, defclass, and definstances constructs all specify the module for the construct by including it as part of the name. The module of a defglobal construct is indicated by specifying the module name after the defglobal keyword. The module of a defmessage handler is specified as part of the class specifier. The module of a defmethod is specified as part of the generic function specifier. For example, the following constructs would be placed in the DETECTION module.
(sensor (name ?name) (value bad)) ⇒ (assert (fault (name ?name))))
(* ?self:flux ?self:flow))
(str-cat ?x ?y))
CLIPS> (clear) CLIPS> (defmodule A) CLIPS> (defmodule B) CLIPS> (defrule foo ⇒) CLIPS> (defrule A::bar ⇒) CLIPS> (list-defrules) bar For a total of 1 defrule. CLIPS> (set-current-module B) A CLIPS> (list-defrules) foo For a total of 1 defrule. CLIPS> 10.3 Specifying ModulesCommands such as undefrule and ppdefrule require the name of a construct on which to operate. In previous versions of CLIPS, constructs were always referred to by their name only, so it was sufficient just to pass the name of the construct to these commands. With modules, however, it is possible to have a construct with the same name in two different modules. The modules associated with a name can be specified either explicitly or implicitly. To explicitly specify a name’s module the module name (a symbol) is listed followed by two colons, ::, and then the name is listed. The module name followed by :: is referred to as a module specifier. For example, MAIN::find stuff, refers to the find stuff construct in the MAIN module. A module can also be implicitly specified since there is always a “current” module. The current module is changed whenever a defmodule construct is defined or the set current module function is used. The MAIN module is automatically defined by CLIPS and by default is the current module when CLIPS is started or after a clear command is issued. Thus the name find stuff would implicitly have the MAIN module as its module when CLIPS is first started.
CLIPS> (defmodule A) CLIPS> (defglobal A ?*x* = 0) CLIPS> (defmodule B) CLIPS> (defglobal B ?*y* = 1) CLIPS> (ppdefglobal y) (defglobal B ?*y* = 1) CLIPS> (ppdefglobal B::y) (defglobal B ?*y* = 1) CLIPS> (ppdefglobal x) [PRNTUTIL1] Unable to find defglobal x CLIPS> (ppdefglobal A::x) (defglobal A ?*x* = 0) CLIPS> 10.4 Importing and Exporting ConstructsUnless specifically exported and imported, the constructs of one module may not be used by another module. A construct is said to be visible or within scope of a module if that construct can be used by the module. For example, if module B wants to use the foo deftemplate defined in module A, then module A must export the foo deftemplate and module B must import the foo deftemplate from module A.
CLIPS> (defmodule A) CLIPS> (deftemplate A::foo (slot x)) CLIPS> (defmodule B) CLIPS> (defrule B::bar (foo (x 3)) ⇒)
(defrule B::bar (foo ( CLIPS> (clear) CLIPS> (defmodule A (export deftemplate foo)) CLIPS> (deftemplate A::foo (slot x)) CLIPS> (defmodule B (import A deftemplate foo)) CLIPS> (defrule B::bar (foo (x 3)) ⇒) CLIPS>
10.4.1 Exporting ConstructsThe export specification in a defmodule definition is used to indicate which constructs will be accessible to other modules importing from the module being defined. Only deftemplates, defclasses, defglobals, deffunctions, and defgenerics may be exported. A module may export any valid constructs that are visible to it (not just constructs that it defines).
10.4.2 Importing ConstructsThe import specification in a defmodule definition is used to indicate which constructs the module being defined will use from other modules. Only deftemplates, defclasses, defglobals, deffunctions, and defgenerics may be imported.
10.5 Importing and Exporting Facts and InstancesFacts and instances are “owned” by the module in which their corresponding deftemplate or defclass is defined, not by the module which creates them. Facts and instances are thus visible only to those modules which import the corresponding deftemplate or defclass. This allows a knowledge base to be partitioned such that rules and other constructs can only “see” those facts and instances which are of interest to them. Note that the initial-fact deftemplate and the INITIAL OBJECT defclass must explicitly be imported from the MAIN module. Rules which have the initial-fact or initial-object pattern added to their LHS (such as a rule thats first CE is a not CE) will not be activated unless the corresponding construct for the pattern is imported.
CLIPS> (clear) CLIPS> (defmodule A (export deftemplate foo bar)) CLIPS> (deftemplate A::foo (slot x)) CLIPS> (deftemplate A::bar (slot y)) CLIPS> (deffacts A::info (foo (x 3)) (bar (y 4))) CLIPS> (defmodule B (import A deftemplate foo)) CLIPS> (reset) CLIPS> (facts A) f-1 (foo (x 3)) f-2 (bar (y 4)) For a total of 2 facts. CLIPS> (facts B) f-1 (foo (x 3)) For a total of 1 fact. CLIPS> 10.5.1 Specifying Instance NamesInstance names are required to be unique within a particular module, but multiple instances of the same name may be in scope at any one time. The syntax of instance names has been extended to allow module specifications (note that the left and right brackets in bold are to be typed and do not indicate an optional part of the syntax).
<instance-name> ::= [<symbol>] | [::<symbol>] | [<module>::symbol>]
10.6 Modules and Rule ExecutionEach module has its own pattern matching network for its rules and its own agenda. When a run command is given, the agenda of the module which is the current focus is executed (note that the reset and clear commands make the MAIN module the current focus). Rule execution continues until another module becomes the current focus, no rules are left on the agenda, or the return function is used from the RHS of a rule. Whenever a module that was focused on runs out of rules on its agenda, the current focus is removed from the focus stack and the next module on the focus stack becomes the current focus. Before a rule executes, the current module is changed to the module in which the executing rule is defined (the current focus). The current focus can be changed by using the focus command. See sections 5.2, 5.4.10.2, 12.12, and 13.12 for more details.
CLIPS> (clear) CLIPS> (defmodule MAIN (export ?ALL)) CLIPS> (defrule MAIN::focus-example ⇒ (printout t “Firing rule in module MAIN.” crlf) (focus A B)) CLIPS> (defmodule A (import MAIN deftemplate initial-fact)) CLIPS> (defrule A::example-rule ⇒ (printout t “Firing rule in module A.” crlf)) CLIPS> (defmodule B (import MAIN deftemplate initial-fact)) CLIPS> (defrule B::example-rule ⇒ (printout t “Firing rule in module B.” crlf)) CLIPS> (reset) CLIPS> (run) Firing rule in module MAIN. Firing rule in module A. Firing rule in module B. CLIPS>
Section 11 Constraint AttributesThis section describes the constraint attributes that can be associated with deftemplates and defclasses so that type checking can be performed on slot values when template facts and instances are created. The constraint information is also analyzed for the patterns on the LHS of a rule to determine if the specified constraints prevent the rule from ever firing.
Syntax <constraint-attribute> ::= <type-attribute> | <allowed-constant-attribute> | <range-attribute> | <cardinality-attribute> 11.1 Type AttributeThe type attribute allows the types of values to be stored in a slot to be restricted. Syntax <type-attribute> ::= (type <type-specification>)
::= SYMBOL | STRING | LEXEME | INTEGER | FLOAT | NUMBER | INSTANCE-NAME | INSTANCE-ADDRESS | INSTANCE | EXTERNAL-ADDRESS | FACT-ADDRESS
11.2 Allowed Constant AttributesThe allowed constant attributes allow the constant values of a specific type which can be stored in a slot to be restricted. The list of values provided should either be a list of constants of the specified type or the keyword ?VARIABLE which means any constant of that type is allowed. The allowed values attribute allows the slot to be restricted to a specific set of values (encompassing all types). Note the difference between using the attribute (allowed symbols red green blue) and (allowed values red green blue). The allowed symbols attribute states that if the value is of type symbol, then its value must be one of the listed symbols. The allowed values attribute completely restricts the allowed values to the listed values. Syntax <allowed-constant-attribute> ::= (allowed-symbols <symbol-list>) | (allowed-strings <string-list>) | (allowed-lexemes <lexeme-list> | (allowed-integers <integer-list>) | (allowed-floats <float-list>) | (allowed-numbers <number-list>) | (allowed-instance-names <instance-list>) | (allowed-values <value-list>)
11.3 Range AttributeThe range attribute allows a numeric range to be specified for a slot when a numeric value is used in that slot. If a numeric value is not used in that slot, then no checking is performed. Syntax <range-attribute> ::= (range <range-specification> <range-specification>)
11.4 Cardinality AttributeThe cardinality attribute restricts the number of fields which can be stored in a multifield slot. This attribute can not be used with a single field slot. Syntax <cardinality-attribute> ::= (cardinality <cardinality-specification> <cardinality-specification>)
11.5 Deriving a Default Value From ConstraintsDefault values for deftemplate and instance slots are automatically derived from the constraints for the slots if an explicit default value is not specified. The following rules are used (in order) to determine the default value for a slot with an unspecified default value. 1) The default type for the slot is chosen from the list of allowed types for the slot in the following order of precedence: SYMBOL, STRING, INTEGER, FLOAT, INSTANCE NAME, INSTANCE ADDRESS, FACT ADDRESS, EXTERNAL ADDRESS. 2) If the default type has an allowed constant restriction specified (such as the allowed-integers attribute for the INTEGER type), then the first value specified in the allowed constant attribute is chosen as the default value.
11.6 Constraint Violation ExamplesThe following examples illustrate some of the types of constraint violations that CLIPS can detect. Example 1 CLIPS> (deftemplate bar (slot a (type SYMBOL INTEGER)) (slot b (type INTEGER FLOAT)) (slot c (type SYMBOL STRING))) CLIPS> (defrule error (bar (a ?x)) (bar (b ?x)) (bar (c ?x)) ⇒)
has constraint conflicts which make the pattern unmatchable
(defrule error-4 (bar (a ?x)) (bar (b ?x)) (bar (c ?x)) ⇒) CLIPS>
Example 2 CLIPS> (deftemplate foo (multislot x (cardinality ?VARIABLE 3))) CLIPS> (deftemplate bar (multislot y (cardinality ?VARIABLE 2))) CLIPS> (deftemplate woz (multislot z (cardinality 7 ?VARIABLE))) CLIPS> (defrule error (foo (x $?x)) (bar (y $?y)) (woz (z $?x $?y)) ⇒)
do not satisfy the cardinality restrictions for slot z
(defrule error (foo (x $?x)) (bar (y $?y)) (woz (z $?x $?y)) ⇒) CLIPS>
Example 3 CLIPS> (deftemplate foo (slot x (type SYMBOL))) CLIPS> (defrule error (foo (x ?x)) (test (> ?x 10)) ⇒)
found in CE #2 to be violated
(defrule error (foo (x ?x)) (test (> ?x 10)) ⇒) CLIPS>
Section 12 Actions And FunctionsThis section describes various actions and functions which may be used on the LHS and RHS of rules, from the top level command prompt, and from other constructs such as deffunctions, defmessage handlers, and defmethods. The terms functions, actions, and commands should be thought of interchangeably. However, when the term function is used it generally refers to a function which returns a value. The term action refers to a function having no return value but performing some basic operation as a side effect (such as printout). The term command refers to functions normally entered at the top level command prompt (such as the reset command, which does not return a value, and the set strategy command, which does return a value). 12.1 Predicate FunctionsThe following functions perform predicate tests. 12.1.1 Testing For NumbersThe numberp function returns the symbol TRUE if its argument is a float or integer, otherwise it returns the symbol FALSE. Syntax (numberp <expression>) 12.1.2 Testing For FloatsThe floatp function returns the symbol TRUE if its argument is a float, otherwise it returns the symbol FALSE. Syntax (floatp <expression>) 12.1.3 Testing For IntegersThe integerp function returns the symbol TRUE if its argument is an integer, otherwise it returns the symbol FALSE. Syntax (integerp <expression>) 12.1.4 Testing For Strings Or SymbolsThe lexemep function returns the symbol TRUE if its argument is a string or symbol, otherwise it returns the symbol FALSE. Syntax (lexemep <expression>) 12.1.5 Testing For StringsThe stringp function returns the symbol TRUE if its argument is a string, otherwise it returns the symbol FALSE. Syntax (stringp <expression>) 12.1.6 Testing For SymbolsThe symbolp function returns the symbol TRUE if its argument is a symbol, otherwise it returns the symbol FALSE. This function may also be called using the name wordp. Syntax (symbolp <expression>) 12.1.7 Testing For Even NumbersThe evenp function returns the symbol TRUE if its argument is an even number, otherwise it returns the symbol FALSE. Syntax (evenp <integer-expression>) 12.1.8 Testing For Odd NumbersThe oddp function returns the symbol TRUE if its argument is an odd number, otherwise it returns the symbol FALSE. Syntax (oddp <integer-expression>) 12.1.9 Testing For Multifield ValuesThe multifieldp function returns the symbol TRUE if its argument is a multifield value, otherwise it returns the symbol FALSE. This function may also be called using the name sequencep. Syntax (multifieldp <expression>) 12.1.10 Testing For External AddressesThe pointerp function returns the symbol TRUE if its argument is an external address, otherwise it returns the symbol FALSE. External address;es are discussed in further detail in the Advanced Programming Guide. Syntax (pointerp <expression>) 12.1.11 Comparing for EqualityThe eq function returns the symbol TRUE if its first argument is equal in value to all its subsequent arguments, otherwise it returns the symbol FALSE. Note that eq compares types as well as values. Thus, (eq 3 3.0) is FALSE since 3 is an integer and 3.0 is a float. Syntax (eq <expression> <expression>+) Example CLIPS> (eq foo bar mumble foo) FALSE CLIPS> (eq foo foo foo foo) TRUE CLIPS> (eq 3 4) FALSE CLIPS> 12.1.12 Comparing for InequalityThe neq function returns the symbol TRUE if its first argument is not equal in value to all its subsequent arguments, otherwise it returns the symbol FALSE. Note that neq compares types as well as values. Thus, (neq 3 3.0) is TRUE since 3 is an integer and 3.0 is a float. Syntax (neq <expression> <expression>+) Example CLIPS> (neq foo bar yak bar) TRUE CLIPS> (neq foo foo yak bar) FALSE CLIPS> (neq 3 a) TRUE CLIPS> 12.1.13 Comparing Numbers for EqualityThe = function returns the symbol TRUE if its first argument is equal in value to all its subsequent arguments, otherwise it returns the symbol FALSE. Note that = compares only numeric values and will convert integers to floats when necessary for comparison. Syntax (= <numeric-expression> <numeric-expression>+) Example CLIPS> (= 3 3.0) TRUE CLIPS> (= 4 4.1) FALSE CLIPS> Portability Note Because the precision of floating point numbers varies from one machine to another, it is possible for the numeric comparison functions to work correctly one machine and incorrectly on another. In fact, you should be aware, even if code is not being ported, that roundoff error can cause erroneous results. For example, the following expression erroneously returns the symbol TRUE because both numbers are rounded up to 0.6666666666666666667.
TRUE CLIPS> 12.1.14 Comparing Numbers for InequalityThe <> function returns the symbol TRUE if its first argument is not equal in value to all its subsequent arguments, otherwise it returns the symbol FALSE. Note that <> compares only numeric values and will convert integers to floats when necessary for comparison. Syntax (<> <numeric-expression> <numeric-expression>+) Example CLIPS> (<> 3 3.0) FALSE CLIPS> (<> 4 4.1) TRUE CLIPS> Portability Note See portability note in section 12.1.13. 12.1.15 Greater Than ComparisonThe > function returns the symbol TRUE if for all its arguments, argument n 1 is greater than argument n, otherwise it returns the symbol FALSE. Note that > compares only numeric values and will convert integers to floats when necessary for comparison. Syntax (> <numeric-expression> <numeric-expression>+) Example CLIPS> (> 5 4 3) TRUE CLIPS> (> 5 3 4) FALSE CLIPS> Portability Note See portability note in section 12.1.13. 12.1.16 Greater Than or Equal ComparisonThe >= function returns the symbol TRUE if for all its arguments, argument n 1 is greater than or equal to argument n, otherwise it returns the symbol FALSE. Note that >= compares only numeric values and will convert integers to floats when necessary for comparison. Syntax (>= <numeric-expression> <numeric-expression>+) Example CLIPS> (>= 5 5 3) TRUE CLIPS> (>= 5 3 5) FALSE CLIPS> Portability Note See portability note in section 12.1.13. 12.1.17 Less Than ComparisonThe < function returns the symbol TRUE if for all its arguments, argument n 1 is less than argument n, otherwise it returns the symbol FALSE. Note that < compares only numeric values and will convert integers to floats when necessary for comparison. Syntax (< <numeric-expression> <numeric-expression>+) Example CLIPS> (< 3 4 5) TRUE CLIPS> (< 3 5 4) FALSE CLIPS> Portability Note See portability note in section 12.1.13. 12.1.18 Less Than or Equal ComparisonThe ⇐ function returns the symbol TRUE if for all its arguments, argument n 1 is less than or equal to argument n, otherwise it returns the symbol FALSE. Note that ⇐ compares only numeric values and will convert integers to floats when necessary for comparison. Syntax (⇐ <numeric-expression> <numeric-expression>+) Example CLIPS> (⇐ 3 5 5) TRUE CLIPS> (⇐ 5 3 5) FALSE CLIPS> Portability Note See portability note in section 12.1.13. 12.1.19 Boolean AndThe and function returns the symbol TRUE if each of its arguments evaluates to TRUE, otherwise it returns the symbol FALSE. The and function performs short circuited boolean logic. Each argument of the function is evaluated from left to right. If any argument evaluates to FALSE, then the symbol FALSE is immediately returned by the function. Syntax (and <expression>+) 12.1.20 Boolean OrThe or function returns the symbol TRUE if any of its arguments evaluates to TRUE, otherwise it returns the symbol FALSE. The or function performs short circuited boolean logic. Each argument of the function is evaluated from left to right. If any argument evaluates to TRUE, then the symbol TRUE is immediately returned by the function. Syntax (or <expression>+) 12.1.21 Boolean NotThe not function returns the symbol TRUE if its argument evaluates to FALSE, otherwise it returns the symbol FALSE. Syntax (not <expression>) 12.2 Multifield FunctionsThe following functions operate on multifield values. 12.2.1 Creating Multifield ValuesThis function appends any number of fields together to create a multifield value. Syntax (create$ <expression>*)
Example CLIPS (create$ hammer drill saw screw pliers wrench) (hammer drill saw screw pliers wrench) CLIPS> (create$ (+ 3 4) (* 2 3) (/ 8 4)) (7 6 2) CLIPS> 12.2.2 Specifying an ElementThe nth$ function will return a specified field from a multifield value. Syntax (nth$ <integer-expression> <multifield-expression>)
Example CLIPS> (nth$ 3 (create$ a b c d e f g)) c CLIPS> 12.2.3 Finding an ElementThe member$ function will tell if a single field value is contained in a multifield value. Syntax (member$ <expression> <multifield-expression>)
Example CLIPS> (member$ blue (create$ red 3 “text” 8.7 blue)) 5 CLIPS> (member$ 4 (create$ red 3 “text” 8.7 blue)) FALSE CLIPS> (member$ (create$ b c) (create$ a b c d)) (2 3) CLIPS> 12.2.4 Comparing Multifield ValuesThis function checks if one multifield value is a subset of another; i.e., if all the fields in the first multifield value are also in the second multifield value. Syntax (subsetp <multifield-expression> <multifield-expression>)
Example CLIPS> (subsetp (create$ hammer saw drill) (create$ hammer drill wrench pliers saw)) TRUE CLIPS> (subsetp (create$ wrench crowbar) (create$ hammer drill wrench pliers saw)) FALSE CLIPS> 12.2.5 Deletion of Fields in Multifield ValuesThis function deletes the specified range from a multifield value. Syntax (delete$ <multifield-expression> <begin-integer-expression> <end-integer-expression>)
Example CLIPS> (delete$ (create$ hammer drill saw pliers wrench) 3 4) (hammer drill wrench) CLIPS> (delete$ (create$ computer printer hard-disk) 1 1) (printer hard-disk) CLIPS> 12.2.6 Creating Multifield Values from Strings.This function constructs a multifield value from a string by using each field in a string as a field in a new multifield value. Syntax (explode$ <string-expression>)
Example
(hammer drill saw screw) CLIPS> (explode$ “1 2 abc 3 4 \”abc\” \“def\”“) (1 2 abc 3 4 “abc” “def”) CLIPS> (explode$ ”?x ~ )“) (”?x“ ”~“ ”)“) CLIPS> 12.2.7 Creating Strings from Multifield ValuesThis function creates a single string from a multifield value. Syntax (implode$ <multifield-expression>)
Example CLIPS> (implode$ (create$ hammer drill screwdriver)) “hammer drill screwdriver wrench pliers saw” CLIPS> (implode$ (create$ 1 “abc” def “ghi” 2)) “1 “abc” def “ghi” 2” CLIPS> (implode$ (create$ “abc def ghi”)) ”“abc def ghi”“ CLIPS> 12.2.8 Extracting a Sub sequence from a Multifield ValueThis function extracts a specified range from a multifield value and returns a new multifield value containing just the sub sequence. Syntax (subseq$ <multifield-value> <begin-integer-expression> <end-integer-expression>)
Example CLIPS> (subseq$ (create$ hammer drill wrench pliers) 3 4) (wrench pliers) CLIPS> (subseq$ (create$ 1 “abc” def “ghi” 2) 1 1) (1) CLIPS> 12.2.9 Replacing Fields within a Multifield ValueThis function replaces a range of field in a multifield value with a series of single field and/or multifield values and returns a new multifield value containing the replacement values within the original multifield value. Syntax (replace$ <multifield-expression> <begin-integer-expression> <end-integer-expression> <single-or-multi-field-expression>+)
Example CLIPS> (replace$ (create$ drill wrench pliers) 3 3 machete) (drill wrench machete) CLIPS> (replace$ (create$ a b c d) 2 3 x y (create$ q r s)) (a x y q r s d) CLIPS> 12.2.10 Inserting Fields within a Multifield ValueThis function inserts a series of single field and/or multifield values at a specified location in a multifield value with and returns a new multifield value containing the inserted values within the original multifield value. Syntax (insert$ <multifield-expression> <integer-expression> <single-or-multi-field-expression>+)
Example CLIPS> (insert$ (create$ a b c d) 1 x) (x a b c d) CLIPS> (insert$ (create$ a b c d) 4 y z) (a b c y z d) CLIPS> (insert$ (create$ a b c d) 5 (create$ q r)) (a b c d q r) CLIPS>
12.2.11 Getting the First Field from a Multifield ValueThis function returns the first field of a multifield value as a multifield value Syntax (first$ <multifield-expression>) Example CLIPS> (first$ (create$ a b c)) (a) CLIPS> (first$ (create$)) () CLIPS> 12.2.12 Getting All but the First Field from a Multifield ValueThis function returns all but the first field of a multifield value as a multifield value. Syntax (rest$ <multifield-expression>) Example CLIPS> (rest$ (create$ a b c)) (b c) CLIPS> (rest$ (create$)) () CLIPS> 12.2.13 Determining the Number of Fields in a Multifield ValueThe length$ function returns an integer indicating the number of fields contained in a multifield value. If the argument passed to length$ is not the appropriate type, a negative one ( 1) is returned. Syntax (length$ <multifield-expression>) Example CLIPS> (length$ (create$ a b c d e f g)) 7 CLIPS> 12.2.14 Deleting Specific Values within a Multifield ValueThis function deletes specific values contained within a multifield value and returns the modified multifield value. Syntax (delete-member$ <multifield-expression> <expression>+)
Example CLIPS> (delete-member$ (create$ a b a c) b a) © CLIPS> (delete-member$ (create$ a b c c b a) (create$ b a)) (a b c c) CLIPS> 12.2.15 Replacing Specific Values within a Multifield ValueThis function replaces specific values contained within a multifield value and returns the modified multifield value. Syntax (replace-member$ <multifield-expression> <substitute-expression> <search-expression>+)
Example CLIPS> (replace-member$ (create$ a b a b) (create$ a b a) a b) (a b a a b a a b a a b a) CLIPS> (replace-member$ (create$ a b a b) (create$ a b a) (create$ a b)) (a b a a b a) CLIPS> 12.3 String FunctionsThe following functions perform operations that are related to strings. 12.3.1 String ConcatenationThe str cat function will concatenates its arguments into a single string. Syntax (str-cat <expression>*)
Example CLIPS> (str-cat “foo” bar) “foobar” CLIPS> 12.3.2 Symbol ConcatenationThe sym cat function will concatenate its arguments into a single symbol. It is functionally identical to the str cat function with the exception that the returned value is a symbol and not a string. Syntax (sym-cat <expression>*)
12.3.3 Taking a String ApartThe sub string function will retrieve a portion of a string from another string. Syntax (sub-string <integer-expression> <integer-expression> <string-expression>)
Example CLIPS> (sub-string 3 8 “abcdefghijkl”) “cdefgh” CLIPS> 12.3.4 Searching a StringThe str index function will return the position of a string inside another string. Syntax (str-index <lexeme-expression> <lexeme-expression>)
Example CLIPS> (str-index “def” “abcdefghi”) 4 CLIPS> (str-index “qwerty” “qwertypoiuyt”) 1 CLIPS> (str-index “qwerty” “poiuytqwer”) FALSE CLIPS> 12.3.5 Evaluating a Function within a StringThe eval function evaluates the string as though it were entered at the command prompt. Syntax (eval <string-or-symbol-expression>)
Example CLIPS> (eval ”(+ 3 4)“) 7 CLIPS> (eval ”(create$ a b c)“) (a b c) CLIPS> 12.3.6 Evaluating a Construct within a StringThe build function evaluates the string as though it were entered at the command prompt. Syntax (build <string-or-symbol-expression>)
Example CLIPS> (clear) CLIPS> (build ”(defrule foo (a) ⇒ (assert (b)))“) TRUE CLIPS> (rules) foo For a total of 1 rule. CLIPS> 12.3.7 Converting a String to UppercaseThe upcase function will return a string or symbol with uppercase alphabetic characters. Syntax (upcase <string-or-symbol-expression>) Example CLIPS> (upcase “This is a test of upcase”) “THIS IS A TEST OF UPCASE” CLIPS> (upcase A_Word_Test_for_Upcase) A_WORD_TEST_FOR_UPCASE CLIPS> 12.3.8 Converting a String to LowercaseThe lowcase function will return a string or symbol with lowercase alphabetic characters. Syntax (lowcase <string-or-symbol-expression>) Example CLIPS> (lowcase “This is a test of lowcase”) “this is a test of lowcase” CLIPS> (lowcase A_Word_Test_for_Lowcase) a_word_test_for_lowcase CLIPS> 12.3.9 Comparing Two StringsThe str compare function will compare two strings to determine their logical relationship (i.e., equal to, less than, greater than). The comparison is performed character by character until the strings are exhausted (implying equal strings) or unequal characters are found. The positions of the unequal characters within the ASCII character set are used to determine the logical relationship of unequal strings. Syntax (str-compare <string-or-symbol-expression> <string-or-symbol-expression>)
Example CLIPS> (< (str-compare “string1” “string2”) 0) TRUE ; since “1” < “2” in ASCII character set CLIPS> (str-compare “abcd” “abcd”) 0 CLIPS> 12.3.10 Determining the Length of a StringThe str length function returns the length of a string as an integer. Syntax (str-length <string-or-symbol-expression>) Example CLIPS> (str-length “abcd”) 4 CLIPS> (str-length xyz) 3 CLIPS> 12.3.11 Checking the Syntax of a Construct or Function Call within a StringThe function check-syntax allows the text representation of a construct or function call to be checked for syntax and semantic errors. Syntax (check-syntax <construct-or-function-string>)
Example CLIPS> (check-syntax ”(defrule example ⇒)“) FALSE CLIPS> (check-syntax ”(defrule foo (number 40000000000000) ⇒)“) (FALSE ”[SCANNER1] WARNING: Over or underflow of long integer. “) CLIPS> (check-syntax ”(defrule example (3) ⇒)“) (” [PRNTUTIL2] Syntax Error: Check appropriate syntax for the first field of a pattern.
(defrule MAIN::example (3 “ FALSE) CLIPS> 12.3.12 Converting a String to a FieldThe string-to-field function parses a string and converts its contents to a primitive data type. Syntax (string-to-field <string-or-symbol-expression>)
Example CLIPS> (string-to-field “3.4”) 3.4 CLIPS> (string-to-field “a b”) a CLIPS> 12.4 The CLIPS I/O SystemCLIPS uses a system called I/O routers to provide very flexible I/O while remaining portable. A more complete discussion of I/O routers is covered in the Advanced Programming Guide. 12.4.1 Logical NamesOne of the key concepts of I/O routing is the use of logical names. Logical names allow reference to an I/O device without having to understand the details of the implementation of the reference. Many functions in CLIPS make use of logical names. A logical name can be either a symbol, a number, or a string. Several logical names are predefined by CLIPS and are used extensively throughout the CLIPS code. These are
12.4.2 Common I/O FunctionsCLIPS provides some of the most commonly needed I/O capabilities through several predefined functions. 12.4.2.1 OpenThe open function allows a user to open a file from the RHS of a rule and attaches a logical name to it. This function takes three arguments: (1) the name of the file to be opened; (2) the logical name which will be used by other CLIPS I/O functions to access the file; and (3) an optional mode specifier. The mode specifier must be one of the following strings:
Syntax (open <file-name> <logical-name> [<mode>])
Example CLIPS> (open “myfile.clp” writeFile “w”) TRUE CLIPS> (open “MS-DOS\\directory\\file.clp” readFile) TRUE CLIPS> 12.4.2.2 CloseThe close function closes a file stream previously opened with the open command. The file is specified by a logical name previously attached to the desired stream. Syntax (close [<logical-name>])
Example CLIPS> (open “myfile.clp” writeFile “w”) TRUE CLIPS> (open “MS-DOS\\directory\\file.clp” readFile) TRUE CLIPS> (close writeFile) TRUE CLIPS> (close writeFile) FALSE CLIPS> (close) TRUE CLIPS> (close) FALSE CLIPS> 12.4.2.3 PrintoutThe function printout allows output to a device attached to a logical name. The logical name must be specified and the device must have been prepared previously for output (e.g., a file must be opened first). To send output to stdout, use a t for the logical name. If the logical name nil is used, the printout function does nothing. Syntax (printout <logical-name> <expression>*)
Example CLIPS> (printout t “Hello there!” crlf) Hello There! CLIPS> (open “data.txt” mydata “w”) TRUE CLIPS> (printout mydata “red green”) CLIPS> (close) TRUE CLIPS> 12.4.2.4 ReadThe read function allows a user to input information for a single field. All of the standard field rules (e.g., multiple symbols must be embedded within quotes) apply. Syntax (read [<logical-name>])
Example CLIPS> (open “data.txt” mydata “w”) TRUE CLIPS> (printout mydata “red green”) CLIPS> (close) TRUE CLIPS> (open “data.txt” mydata) TRUE CLIPS> (read mydata) red CLIPS> (read mydata) green CLIPS> (read mydata) EOF CLIPS> (close) TRUE CLIPS> 12.4.2.5 ReadlineThe readline function is similar to the read function, but it allows a whole string to be input instead of a single field. Normally, read will stop when it encounters a delimiter. The readline function only stops when it encounters a carriage return, a semicolon, or an EOF. Any tabs or spaces in the input are returned by readline as a part of the string. The readline function returns a string. Syntax (readline [<logical-name>])
Example CLIPS> (open “data.txt” mydata “w”) TRUE CLIPS> (printout mydata “red green”) CLIPS> (close) TRUE CLIPS> (open “data.txt” mydata) TRUE CLIPS> (readline mydata) “red green” CLIPS> (readline mydata) EOF CLIPS> (close) TRUE CLIPS> 12.4.2.6 FormatThe format function allows a user to send formatted output to a device attached to a logical name. It can be used in place of printout when special formatting of output information is desired. Although a slightly more complicated function, format provides much better control over how the output is formatted. The format commands are similar to the printf statement in C. The format function always returns a string containing the formatted output. A logical name of nil may be used when the formatted return string is desired without writing to a device. Syntax (format <logical-name> <string-expression> <expression>*)
Example CLIPS> (format t “Hello World!%n”) Hello World! “Hello World! ” CLIPS> (format nil “Integer: |%ld|” 12) “Integer: |12|” CLIPS> (format nil “Integer: |%4ld|” 12) “Integer: | 12|” CLIPS> (format nil “Integer: |%-04ld|” 12) “Integer: |12 |” CLIPS> (format nil “Float: |%f|” 12.01) “Float: |12.010000|” CLIPS> (format nil “Float: |%7.2f| “12.01) “Float: | 12.01| ” CLIPS> (format nil “Test: |%e|” 12.01) “Test: |1.201000e+01|” CLIPS> (format nil “Test: |%7.2e|” 12.01) “Test: |1.20e+01|” CLIPS> (format nil “General: |%g|” 1234567890) “General: |1.23457e+09|” CLIPS> (format nil “Hexadecimal: |%x|” 12) “Hexadecimal: |c|” CLIPS> (format nil “Octal: |%o|” 12) “Octal: |14|” CLIPS> (format nil “Symbols: |%s| |%s|” value-a1 capacity) “Symbols: |value-a1| |capacity|” CLIPS> Portability Note The format function uses the C function sprintf as a base. Some systems may not support sprintf or may not support all of these features, which may affect how format works. 12.4.2.7 RenameThe rename function is used to change the name of a file. Syntax (rename <old-file-name> <new-file-name>)
The rename function uses the ANSI C function rename as a base. If the ANSI_COMPILER flag was disabled when CLIPS was compiled, then this function will be non functional and always return FALSE. 12.4.2.8 RemoveThe remove function is used to delete a file. Syntax (remove <file-name>)
The remove function uses the ANSI C function remove as a base. If the ANSI_COMPILER flag was disabled when CLIPS was compiled, then this function will be non functional and always return FALSE. 12.5 Math FunctionsCLIPS provides several functions for mathematical computations. They are split into two packages: a set of standard math functions and a set of extended math functions. 12.5.1 Standard Math FunctionsThe standard math functions are listed below. These functions should be used only on numeric arguments. An error message will be printed if a string argument is passed to a math function. 12.5.1.1 AdditionThe + function returns the sum of its arguments. Each of its arguments should be a numeric expression. Addition is performed using the type of the arguments provided unless mixed mode arguments (integer and float) are used. In this case, the function return value and integer arguments are converted to floats after the first float argument has been encountered. This function returns a float if any of its arguments is a float, otherwise it returns an integer. Syntax (+ <numeric-expression> <numeric-expression>+) Example CLIPS> (+ 2 3 4) 9 CLIPS> (+ 2 3.0 5) 10.0 CLIPS> (+ 3.1 4.7) 7.8 CLIPS> 12.5.1.2 SubtractionThe function returns the value of the first argument minus the sum of all subsequent arguments. Each of its arguments should be a numeric expression. Subtraction is performed using the type of the arguments provided unless mixed mode arguments (integer and float) are used. In this case, the function return value and integer arguments are converted to floats after the first float argument has been encountered. This function returns a float if any of its arguments is a float, otherwise it returns an integer. Syntax (- <numeric-expression> <numeric-expression>+) Example CLIPS> (- 12 3 4) 5 CLIPS> (- 12 3.0 5) 4.0 CLIPS> (- 4.7 3.1) 1.6 CLIPS> 12.5.1.3 MultiplicationThe * function returns the product of its arguments. Each of its arguments should be a numeric expression. Multiplication is performed using the type of the arguments provided unless mixed mode arguments (integer and float) are used. In this case, the function return value and integer arguments are converted to floats after the first float argument has been encountered. This function returns a float if any of its arguments is a float, otherwise it returns an integer. Syntax (* <numeric-expression> <numeric-expression>+) Example CLIPS> (* 2 3 4) 24 CLIPS> (* 2 3.0 5) 30.0 CLIPS> (* 3.1 4.7) 14.57 CLIPS> 12.5.1.4 DivisionThe / function returns the value of the first argument divided by each of the subsequent arguments. Each of its arguments should be a numeric expression. Division is performed using the type of the arguments provided unless mixed mode arguments (integer and float) are used. In this case, the function return value and integer arguments are converted to floats after the first float argument has been encountered. By default, the dividend (the first argument) is automatically converted to a floating point number so that the result is a floating pointer number. The function set auto float dividend can be used to control this behavior. If for example, the auto float feature is disabled, the expression (/ 4 3 4.0) evaluates to 0.25 as opposed to 0.333333333 if this feature were enabled. This function returns a float if any of its arguments is a float, otherwise it returns an integer. Syntax (/ <numeric-expression> <numeric-expression>+) Example CLIPS> (/ 4 2) 2.0 CLIPS> (/ 4.0 2.0) 2.0 CLIPS> (/ 24 3 4) 2.0 CLIPS> 12.5.1.5 Integer DivisionThe div function returns the value of the first argument divided by each of the subsequent arguments. Each of its arguments should be a numeric expression. Each argument is automatically converted to an integer and integer division is performed. This function returns an integer. Syntax (div <numeric-expression> <numeric-expression>+) Example CLIPS> (div 4 2) 2 CLIPS> (div 5 2) 2 CLIPS> (div 33 2 3 5) 1 CLIPS> 12.5.1.6 Maximum Numeric ValueThe max function returns the value of its largest numeric argument. Each of its arguments should be a numeric expression. When necessary, integers are temporarily converted to floats for comparison. The return value will either be integer or float (depending upon the type of the largest argument). Syntax (max <numeric-expression>+) Example CLIPS> (max 3.0 4 2.0) 4 CLIPS> 12.5.1.7 Minimum Numeric ValueThe min function returns the value of its smallest numeric argument. Each of its arguments should be a numeric expression. When necessary, integers are temporarily converted to floats for comparison. The return value will either be integer or float (depending upon the type of the smallest argument). Syntax (min <numeric-expression>+) Example CLIPS> (min 4 0.1 -2.3) -2.3 CLIPS> 12.5.1.8 Absolute ValueThe abs function returns the absolute value of its only argument (which should be a numeric expression). The return value will either be integer or float (depending upon the type the argument). Syntax (abs <numeric-expression>) Example CLIPS> (abs 4.0) 4.0 CLIPS> (abs -2) 2 CLIPS> 12.5.1.9 Convert To FloatThe float function converts its only argument (which should be a numeric expression) to type float and returns this value. Syntax (float <numeric-expression>) Example CLIPS> (float 4.0) 4.0 CLIPS> (float -2) -2.0 CLIPS> 12.5.1.10 Convert To IntegerThe integer function converts its only argument (which should be a numeric expression) to type integer and returns this value. Syntax (integer <numeric-expression>) Example CLIPS> (integer 4.0) 4 CLIPS> (integer -2) -2 CLIPS> 12.5.2 Extended Math FunctionsIn addition to standard math functions, CLIPS also provides a large number of scientific and trigonometric math functions for more extensive computations. Although included in the generic version of CLIPS, if an expert system does not need these capabilities, these functions may be excluded from the executable element of CLIPS to provide more memory (see the Advanced Programming Guide).
These mathematical functions use the C library math.h. If the user’s system does not support this library, the user needs to make some adjustments to math.c. The system dependent math functions are called from CosFunction, SinFunction, etc. The user must change each of these to call the appropriate functions from his/her system. The user also must make sure that the functions CosFunction, SinFunction, etc., always return double precision floating point numbers. To link these functions, most compilers provide a separate math library that must be included during linking. 12.5.2.1 Trigonometric FunctionsThe following trigonometric functions take one numeric argument and return a floating point number. The argument is expected to be in radians.
Example CLIPS> (cos 0) 1.0 CLIPS> (acos 1.0) 0.0 CLIPS> 12.5.2.2 Convert From Degrees to GradsThe deg grad function converts its only argument (which should be a numeric expression) from units of degrees to units of grads (360 degrees = 400 grads). The return value of this function is a float. Syntax (deg-grad <numeric-expression>) Example CLIPS> (deg-grad 90) 100.0 CLIPS> 12.5.2.3 Convert From Degrees to RadiansThe deg rad function converts its only argument (which should be a numeric expression) from units of degrees to units of radians (360 degrees = 2π radians). The return value of this function is a float. Syntax (deg-rad <numeric-expression>) Example CLIPS> (deg-rad 180) 3.141592653589793 CLIPS> 12.5.2.4 Convert From Grads to DegreesThe grad deg function converts its only argument (which should be a numeric expression) from units of grads to units of degrees (360 degrees = 400 grads). The return value of this function is a float. Syntax (grad-deg <numeric-expression>) Example CLIPS> (grad-deg 100) 90.0 CLIPS> 12.5.2.5 Convert From Radians to DegreesThe rad deg function converts its only argument (which should be a numeric expression) from units of radians to units of degrees (360 degrees = 2π radians). The return value of this function is a float. Syntax (rad-deg <numeric-expression>) Example CLIPS> (rad-deg 3.141592653589793) 180.0 CLIPS> 12.5.2.6 Return the Value of πThe pi function returns the value of π (3.141592653589793…) as a float. Syntax (pi) Example CLIPS> (pi) 3.141592653589793 CLIPS> 12.5.2.7 Square RootThe sqrt function returns the square root of its only argument (which should be a numeric expression) as a float. Syntax (sqrt <numeric-expression>) Example CLIPS> (sqrt 9) 3.0 CLIPS> 12.5.2.8 PowerThe ** function raises its first argument to the power of its second argument and returns this value as a float. Syntax (** <numeric-expression> <numeric-expression>) Example CLIPS> (** 3 2) 9.0 CLIPS> 12.5.2.9 ExponentialThe exp function raises the value e (the base of the natural system of logarithms, having a value of approximately 2.718…) to the power specified by its only argument and returns this value as a float. Syntax (exp <numeric-expression>) Example CLIPS> (exp 1) 2.718281828459045 CLIPS> 12.5.2.10 LogarithmGiven n (the only argument) and the value e is the base of the natural system of logarithms, the log function returns the float value x such that the following equation is satisfied:
Syntax (log <numeric-expression>) Example CLIPS> (log 2.718281828459045) 0.9999999999999999 CLIPS> 12.5.2.11 Logarithm Base 10Given n (the only argument), the log10 function returns the float value x such that the following equation is satisfied:
Syntax (log10 <numeric-expression>) Example CLIPS> (log10 100) 2.0 CLIPS> 12.5.2.12 RoundThe round function rounds its only argument (which should be a numeric expression) toward the closest integer. If the argument is exactly between two integers, it is rounded down. The return value of this function is an integer. Syntax (round <numeric-expression>) Example CLIPS> (round 3.6) 4 CLIPS> 12.5.2.13 ModulusThe mod function returns the remainder of the result of dividing its first argument by its second argument (assuming that the result of division must be an integer). It returns an integer if both arguments are integers, otherwise it returns a float. Syntax (mod <numeric-expression> <numeric-expression>) Example CLIPS> (mod 5 2) 1 CLIPS> (mod 3.7 1.2) 0.1 CLIPS> 12.6 Procedural FunctionsThe following are functions which provide procedural programming capabilities as found in languages such as Pascal, C and Ada. 12.6.1 Binding VariablesOccasionally, it is important to create new variables or to modify the value of previously bound variables on the RHS of a rule. The bind function provides this capability. Syntax (bind <variable> <expression>*)
Example 1 CLIPS> (defglobal ?*x* = 3.4) CLIPS> ?*x* 3.4 CLIPS> (bind ?*x* (+ 8 9)) 17 CLIPS> ?*x* 17 CLIPS> (bind ?*x* (create$ a b c d)) (a b c d) CLIPS> ?*x* (a b c d) CLIPS> (bind ?*x* d e f) (d e f) CLIPS> ?*x* (d e f) CLIPS> (bind ?*x*) 3.4 CLIPS> ?*x* 3.4 CLIPS> Example 2 CLIPS> (defclass A (is-a USER) (role concrete) (slot x) (slot y)) CLIPS> (defmessage-handler A init after () (bind ?self:x 3) (bind ?self:y 4)) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] print) [a] of A (x 3) (y 4) CLIPS> 12.6.2 If...then...else FunctionThe if function provides an if…then…else structure to allow for conditional execution of a set of actions. Syntax
(if <expression>
Example
(defrule closed-valves
12.6.3 WhileThe while function is provided to allow simple looping. Its use is similar to that of the if function. Syntax
(while <expression> [do]
Example
(defrule open-valves
(printout t “Valve ” ?v ” is open“ crlf) 12.6.4 Loop-for-countThe loop for count function is provided to allow simple iterative looping. Syntax (loop-for-count <range-spec> [do] <action>*)
(<loop-variable> <start-index> <end-index>) | (<loop-variable> <end-index>) <start-index> ::= <integer-expression> <end-index> ::= <integer-expression>
Example CLIPS> (loop-for-count 2 (printout t “Hello world” crlf)) Hello world Hello world FALSE CLIPS> (loop-for-count (?cnt1 2 4) do (loop-for-count (?cnt2 1 3) do (printout t ?cnt1 ” “ ?cnt2 crlf))) 2 1 2 2 2 3 3 1 3 2 3 3 4 1 4 2 4 3 FALSE CLIPS> 12.6.5 PrognThe progn function evaluates all of its arguments and returns the value of the last argument;. Syntax (progn <expression>*) Example CLIPS> (progn (setgen 5) (gensym)) gen5 CLIPS> 12.6.6 Progn$The progn$ function performs a set of actions for each field of a multifield value. The field of the current iteration can be examined with <loop variable>, if specified. The index of the current iteration can be examined with <loop variable> index. The progn$ function can use variables from outer scopes, and the return and break functions can also be used within a progn$ as long as they are valid in the outer scope. The return value of this function is the return value of the last action performed for the last field in the multifield value. Syntax (progn$ <list-spec> <expression>*)
(<list-variable> <multifield-expression>) Example CLIPS> (progn$ (?field (create$ abc def ghi)) (printout t ”–> “ ?field ” “ ?field-index ” ←-“ crlf)) –> abc 1 ←- –> def 2 ←- –> ghi 3 ←- CLIPS> 12.6.7 ReturnThe return function immediately terminates the currently executing deffunction, generic function method, message handler, defrule RHS, or certain instance set query functions (do for instance, do for all instances and delayed do for all instances). Without any arguments, there is no return value. However, if an argument is included, its evaluation is given as the return value of the deffunction , method or message handler.
Syntax (return [<expression>]) Example CLIPS> (deffunction sign (?num) (if (> ?num 0) then (return 1)) (if (< ?num 0) then (return -1)) 0) CLIPS> (sign 5) 1 CLIPS> (sign -10) -1 CLIPS> (sign 0) 0 CLIPS> 12.6.8 BreakThe break function immediately terminates the currently iterating while loop, loop-for-count execution, progn execution, progn$ execution, or certain instance set query functions (do for instance, do for all instances and delayed do for all instances).
Syntax (break) Example CLIPS> (deffunction iterate (?num) (bind ?i 0) (while TRUE do (if (>= ?i ?num) then (break)) (printout t ?i ” “) (bind ?i (+ ?i 1))) (printout t crlf)) CLIPS> (iterate 1) 0 CLIPS> (iterate 10) 0 1 2 3 4 5 6 7 8 9 CLIPS> 12.6.9 SwitchThe switch function allows a particular group of actions (among several groups of actions) to be performed based on a specified value. Syntax (switch <test-expression> <case-statement>* [<default-statement>]) <case-statement> ::= (case <comparison-expression> then <action>*) <default-statement> ::= (default <action>*)
Example
CLIPS> (defglobal ?*y* = 1) CLIPS> (deffunction foo (?val) (switch ?val (case ?*x* then *x*) (case ?*y* then *y*) (default none))) CLIPS> (foo 0) *x* CLIPS> (foo 1) *y* CLIPS> (foo 2) none CLIPS> 12.7 Miscellaneous FunctionsThe following are additional functions for use within CLIPS. 12.7.1 GensymThe gensym function returns a special, sequenced symbol that can be stored as a single field. This is primarily for tagging patterns that need a unique identifier, but the user does not care what the identifier is. Multiple calls to gensym are guaranteed to return different identifiers of the form
Example (assert (new-id (gensym) flag1 7))
12.7.2 Gensym*The gensym* function is similar to the gensym function, however, it will produce a unique symbol that does not currently exist within the CLIPS environment. Example CLIPS> (setgen 1) 1 CLIPS> (assert (gen1 gen2 gen3)) <Fact-0> CLIPS> (gensym) gen1 CLIPS> (gensym*) gen4 CLIPS> 12.7.3 SetgenThe setgen function allows the user to set the starting number used by gensymand gensym* (see sections 12.7.1 and 12.7.2). Syntax (setgen <integer-expression>)
Example CLIPS> (setgen 32) 32 CLIPS>
12.7.4 RandomThe random function returns a “random” integer value. It is patterned after the ANSI standard rand library function and therefore may not be available on all platforms. Syntax (random [<start-integer-expression> <end-integer-expression>])
Example
(defrule roll-the-dice (bind ?roll1 (random 1 6)) (bind ?roll2 (random 1 6)) (printout t “Your roll is: ” ?roll1 ” “ ?roll2 crlf))
If the ANSI_COMPILER flag has not been set, this function compiles to a non functional stub that always returns zero. 12.7.5 SeedThe seed function seeds the random number generator. It is patterned after the ANSI standard seed library function and therefore may not be available on all platforms. Syntax (seed <integer-expression>)
If the ANSI_COMPILER flag has not been set, this function compiles to a non functional stub. 12.7.6 TimeThe time function returns a floating point value representing the elapsed seconds since the system reference time. Syntax (time)
Not all operating systems/compilers provide this function. The code is stored in the sysdep.c file, and the default coding for generic CLIPS is a non functional stub that returns zero for the time. 12.7.7 Number of Fields or Characters in a Data ObjectThe length function returns an integer for the number of fields bound to a multifield value or the length in characters of a string or symbol. Syntax (length <string-symbol-or-multifield-expression>)
Example CLIPS> (length (create$ a b c d e f g)) 7 CLIPS> (length “cat”) 3 CLIPS> 12.7.8 Determining the Restrictions for a FunctionThe get function restrictions function can be used to gain access to the restriction string associated with a CLIPS or user defined function. The restriction string contains information on the number and types of arguments that a function expects. See section 3.1 of the Advanced Programming Guide for the meaning of the characters which compose the restriction string. Syntax (get-function-restrictions <function-name>) Example CLIPS> (get-function-restrictions +) “2*n” CLIPS> 12.7.9 Sorting a List of ValuesThe function sort allows a list of values to be sorted based on a user specified comparison function. Syntax (sort <comparison-function-name> <expression>*)
Example CLIPS> (sort > 4 3 5 7 2 7) (2 3 4 5 7 7) CLIPS> (deffunction string> (?a ?b) (> (str-compare ?a ?b) 0)) CLIPS> (sort string> ax aa bk mn ft m) (aa ax bk ft m mn) CLIPS> 12.7.10 Calling a FunctionThe function funcall constructs a function call from its arguments and then evaluates the function call. The first argument should be the name of a user-defined function, deffunction, or generic function. The remaining arguments are evaluated and then passed to the specified function when it is evaluated. Syntax (funcall (function-name> <expression>*) Example CLIPS> (funcall + 1 (create$ 2 3) 4) 10 CLIPS> 12.7.11 Timing Functions and CommandsThe function timer returns the number of seconds elapsed evaluating a series of expressions. Syntax (timer <expression>*) Example CLIPS> (timer (loop-for-count 10000 (+ 3 4))) 0.0416709999999512 CLIPS> 12.8 Deftemplate FunctionsThe following functions provide ancillary capabilities for the deftemplate construct. 12.8.1 Getting the List of DeftemplatesThe function get deftemplate list returns a multifield value containing the names of all deftemplate constructs facts visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all deftemplates are returned. Syntax (get deftemplate list [<module-name>]) Example CLIPS> (clear) CLIPS> (get-deftemplate-list) () CLIPS> (deftemplate foo) CLIPS> (deftemplate bar) CLIPS> (get-deftemplate-list) (foo bar) CLIPS> 12.8.2 Determining the Module in which a Deftemplate is DefinedThis function returns the module in which the specified deftemplate name is defined. Syntax (deftemplate module <deftemplate-name>) 12.9 Fact FunctionsThe following actions are used for assert, retracting, and modifying facts. 12.9.1 Creating New FactsTheassert action allows the user to add a fact to the fact list. Multiple facts may be asserted with each call. If the facts item is being watched (see section 13.2), then an informational message will be printed each time a fact is asserted. Syntax (assert <RHS-pattern>+)
Example CLIPS> (clear) CLIPS> (assert (color red)) <Fact-0> CLIPS> (assert (color blue) (value (+ 3 4))) <Fact-2> CLIPS> (assert (color red)) FALSE CLIPS> (deftemplate status (slot temp) (slot pressure)) CLIPS> (assert (status (temp high) (pressure low))) <Fact-3> CLIPS> (facts) f-0 (color red) f-1 (color blue) f-2 (value 7) f-3 (status (temp high) (pressure low)) For a total of 4 facts. CLIPS> 12.9.2 Removing Facts from the Fact listThe retract action allows the user to remove facts from the fact list. Multiple facts may be retracted with a single retract statement. The retraction of a fact also removes all rules that depended upon that fact for activation from the agenda. Retraction of a fact may also cause the retraction of other facts which receive logical support from the retracted fact. If the facts item is being watched (see section 13.2), then an informational message will be printed each time a fact is retracted. Syntax (retract <retract-specifier>+ | *)
Example
(defrule change-valve-status 12.9.3 Modifying Template FactsThe modify action allows the user to modify template facts on the fact list. Only one fact may be modified with a single modify statement. The modification of a fact is equivalent to retracting the present fact and asserting the modified fact. Therefore, any facts receiving logical support from a template fact are retracted (assuming no other support) when the template fact is modified and the new template fact loses any logical support that it previously had. Syntax (modify <fact-specifier> <RHS-slot>*)
Example
(defrule change-valve-status 12.9.4 Duplicating Template FactsThe duplicate action allows the user to duplicate deftemplate facts on the fact list changing a group of specified fields. This command allows a new fact to be created by copying most of the fields of a source fact and then specifying the fields to be changed. Only one fact may be duplicated with a single duplicate statement. The duplicate command is similar to the modify command except the fact being duplicated is not retracted. Syntax (duplicate <fact-specifier> <RHS-slot>*)
Example
(defrule duplicate-part 12.9.5 Asserting a StringTheassert string function is similar to assert in that it will add a fact to the fact list. However, assert string takes a single string representing a fact (expressed in either ordered or deftemplate format ) and asserts it. Only one fact may be asserted with each assert string statement. Syntax (assert-string <string-expression>)
Example CLIPS> (clear) CLIPS> (deftemplate foo (slot x) (slot y)) CLIPS> (assert-string ”(status valve open)“) CLIPS> (assert-string ”(light \“red\”)“) CLIPS> (assert-string ”(a\\b \“c\\\\d\”)“) CLIPS> (assert-string ”(foo (x 3))“) CLIPS> (assert-string ”(foo (y 7))“) CLIPS> (facts) f-0 (status valve open) f-1 (light “red”) f-2 (a\b “c\d”) f-3 (foo (x 3) (y nil)) f-4 (foo (x nil) (y 7)) For a total of 5 facts. CLIPS> 12.9.6 Getting the Fact Index of a Fact addressThe fact index function returns the fact index (an integer) of a fact address. Syntax (fact-index <fact-address>) Example
(defrule print-fact-indices 12.9.7 Determining If a Fact ExistsThe fact existp returns TRUE if the fact specified by its fact-index or fact-address arguments exists, otherwise FALSE is returned. Syntax (fact-existp <fact-address-or-index>) Example CLIPS> (clear) CLIPS> (defglobal ?*x* = (assert (example fact))) CLIPS> (facts) f-0 (example fact) For a total of 1 fact. CLIPS> (fact-existp 0) TRUE CLIPS> (retract 0) CLIPS> (fact-existp ?*x*) FALSE CLIPS> 12.9.8 Determining the Deftemplate (Relation) Name Associated with a FactThe fact relation function returns the deftemplate (relation) name associated with the fact. FALSE is returned if the specified fact does not exist. Syntax (fact-relation <fact-address-or-index>) Example CLIPS> (clear) CLIPS> (assert (example fact)) <Fact-0> CLIPS> (fact-relation 0) example CLIPS> 12.9.9 Determining the Slot Names Associated with a FactThe fact slot-names function returns the slot names associated with the fact in a multifield value. The symbol implied is returned for an ordered fact (which has a single implied multifield slot). FALSE is returned if the specified fact does not exist. Syntax (fact-slot-names <fact-address-or-index>) Example CLIPS> (clear) CLIPS> (deftemplate foo (slot bar) (multislot yak)) CLIPS> (assert (foo (bar 1) (yak 2 3))) <Fact-0> CLIPS> (fact-slot-names 0) (bar yak) CLIPS> (assert (another a b c)) <Fact-1> CLIPS> (fact-slot-names 1) (implied) CLIPS> 12.9.10 Retrieving the Slot Value of a FactThe fact slot-value function returns the value of the specified slot from the specified fact. The symbol implied should be used as the slot name for the implied multifield slot of an ordered fact. FALSE is returned if the slot name argument is invalid or the specified fact does not exist. Syntax (fact-slot-value <fact-address-or-index> <slot-name>) Example CLIPS> (clear) CLIPS> (deftemplate foo (slot bar) (multislot yak)) CLIPS> (assert (foo (bar 1) (yak 2 3))) <Fact-0> CLIPS> (fact-slot-value 0 bar) 1 CLIPS> (fact-slot-value 0 yak) (2 3) CLIPS> (assert (another a b c)) <Fact-1> CLIPS> (fact-slot-value 1 implied) (a b c) CLIPS> 12.9.11 Retrieving the Fact-ListThe get-fact-list function returns a multifield containing the list of facts visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all facts are returned. Syntax (get-fact-list [<module-name>]) Example CLIPS> (clear) CLIPS> (assert (a)) <Fact-0> CLIPS> (get-fact-list) (<Fact-0>) CLIPS> (defmodule B) CLIPS> (assert (b)) <Fact-1> CLIPS> (get-fact-list) (<Fact-1>) CLIPS> (get-fact-list MAIN) (<Fact-0>) CLIPS> (get-fact-list *) (<Fact-0> <Fact-1>) CLIPS> 12.10 Deffacts FunctionsThe following functions provide ancillary capabilities for the deffacts construct. 12.10.1 Getting the List of DeffactsThe function get deffacts list returns a multifield value containing the names of all deffacts constructs visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all deffacts are returned. Syntax (get deffacts list [<module-name>]) Example CLIPS> (clear) CLIPS> (get-deffacts-list) (initial-fact) CLIPS> (deffacts foo) CLIPS> (get-deffacts-list) (initial-fact foo) CLIPS> 12.10.2 Determining the Module in which a Deffacts is DefinedThis function returns the module in which the specified deffacts name is defined. Syntax (deffacts module <deffacts-name>) 12.11 Defrule FunctionsThe following functions provide ancillary capabilities for the defrule construct. 12.11.1 Getting the List of DefrulesThe function get defrule list returns a multifield value containing the names of all defrule constructs visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all defrules are returned. Syntax (get defrule list) Example CLIPS> (clear) CLIPS> (get-defrule-list) () CLIPS> (defrule foo ⇒) CLIPS> (defrule bar ⇒) CLIPS> (get-defrule-list) (foo bar) CLIPS> 12.11.2 Determining the Module in which a Defrule is DefinedThis function returns the module in which the specified defrule name is defined. Syntax (defrule module <defrule-name>) 12.12 Agenda FunctionsThe following functions provide ancillary capabilities manipulating the agenda. 12.12.1 Getting the Current FocusThe function get focus returns the module name of the current focus. If the focus stack is empty, then the symbol FALSE is returned. Syntax (get focus) Example CLIPS> (clear) CLIPS> (get-focus) MAIN CLIPS> (defmodule A) CLIPS> (defmodule B) CLIPS> (focus A B) TRUE CLIPS> (get-focus) A CLIPS> 12.12.2 Getting the Focus StackThe function get focus stack returns all of the module names in the focus stack as a multifield value. A multifield value of length zero is returned if the focus stack is empty. Syntax (get focus stack) Example CLIPS> (clear) CLIPS> (get-focus-stack) (MAIN) CLIPS> (clear-focus-stack) CLIPS> (get-focus-stack) () CLIPS> (defmodule A) CLIPS> (defmodule B) CLIPS> (focus A B) TRUE CLIPS> (get-focus-stack) (A B) CLIPS> 12.12.3 Removing the Current Focus from the Focus StackThe function pop focus removes the current focus from the focus stack and returns the module name of the current focus. If the focus stack is empty, then the symbol FALSE is returned. Syntax (pop focus) Example CLIPS> (clear) CLIPS> (list-focus-stack) MAIN CLIPS> (pop-focus) MAIN CLIPS> (defmodule A) CLIPS> (defmodule B) CLIPS> (focus A B) TRUE CLIPS> (list-focus-stack) A B MAIN CLIPS> (pop-focus) A CLIPS> (list-focus-stack) B CLIPS> 12.13 Defglobal FunctionsThe following functions provide ancillary capabilities for the defglobal construct. 12.13.1 Getting the List of DefglobalsThe function get defglobal list returns a multifield value containing the names of all global variables visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all globals are returned. Syntax (get defglobal list [<module-name>]) Example CLIPS> (clear) CLIPS> (get-defglobal-list) () CLIPS> (defglobal ?*x* = 3 ?*y* = 5) CLIPS> (get-defglobal-list) (x y) CLIPS> 12.13.2 Determining the Module in which a Defglobal is DefinedThis function returns the module in which the specified defglobal name is defined. Syntax (defglobal module <defglobal-name>) 12.14 Deffunction FunctionsThe following functions provide ancillary capabilities for the deffunction construct. 12.14.1 Getting the List of DeffunctionsThe function get deffunction list returns a multifield value containing the names of all deffunction constructs visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all deffunctions are returned. Syntax (get deffunction list [<module-name>]) Example CLIPS> (clear) CLIPS> (get-deffunction-list) () CLIPS> (deffunction foo ()) CLIPS> (deffunction bar ()) CLIPS> (get-deffunction-list) (foo bar) CLIPS> 12.14.2 Determining the Module in which a Deffunction is DefinedThis function returns the module in which the specified deffunction name is defined. Syntax (deffunction module <deffunction-name>) 12.15 Generic Function FunctionsThe following functions provide ancillary capabilities for generic function methods. 12.15.1 Getting the List of DefgenericsThe function get defgeneric list returns a multifield value containing the names of all defgeneric constructs that are currently defined. Syntax (get defgeneric list) Example CLIPS> (clear) CLIPS> (get-defgeneric-list) () CLIPS> (defgeneric foo) CLIPS> (defgeneric bar) CLIPS> (get-defgeneric-list) (foo bar) CLIPS> 12.15.2 Determining the Module in which a Generic Function is DefinedThis function returns the module in which the specified defgeneric name is defined. Syntax (defgeneric module <defgeneric-name>) 12.15.3 Getting the List of DefmethodsThe function get defmethod list returns a multifield value containing method name/indices pairs for all defmethod constructs that are currently defined. The optional generic function name parameter restricts the methods return to only those of the specified generic function. Syntax (get defmethod list [<generic-function-name>]) Example CLIPS> (clear) CLIPS> (get-defmethod-list) () CLIPS> (defmethod foo ((?x STRING))) CLIPS> (defmethod foo ((?x INTEGER))) CLIPS> (defmethod bar ((?x STRING))) CLIPS> (defmethod bar ((?x INTEGER))) CLIPS> (get-defmethod-list) (foo 1 foo 2 bar 1 bar 2) CLIPS> (get-defmethod-list foo) (foo 1 foo 2) CLIPS> 12.15.4 Type DeterminationThe function type returns a symbol which is the name of the type (or class) of its of argument. This function is equivalent to the class function (see section 12.16.4.4), but, unlike the class function, it is available even when COOL is not installed. Syntax (type <expression>) Example CLIPS> (type (+ 2 2)) INTEGER CLIPS> (defclass CAR (is-a USER) (role concrete)) CLIPS> (make-instance Rolls-Royce of CAR) [Rolls-Royce] CLIPS> (type Rolls-Royce) SYMBOL CLIPS> (type [Rolls-Royce]) CAR CLIPS> 12.15.5 Existence of Shadowed MethodsIf called from a method for a generic function, the function next methodp will return the symbol TRUE if there is another method shadowed (see section 8.5.3) by the current one. Otherwise, the function will return the symbol FALSE. Syntax (next methodp) 12.15.6 Calling Shadowed MethodsIf the conditions are such that the function next methodpwould return the symbol TRUE (see section 12.15.5), then calling the function call next method will execute the shadowed (see section 8.5.3) method. Otherwise, a method execution error will occur (see section 8.5.4). In the event of an error, the return value of this function is the symbol FALSE, otherwise it is the return value of the shadowed method. The shadowed method is passed the same arguments as the calling method.
Syntax (call next method) Example CLIPS> (defmethod describe ((?a INTEGER)) (if (next-methodp) then (bind ?extension (str-cat ” “ (call-next-method))) else (bind ?extension ”“)) (str-cat “INTEGER” ?extension)) CLIPS> (describe 3) “INTEGER” CLIPS> (defmethod describe ((?a NUMBER)) “NUMBER”) CLIPS> (describe 3) “INTEGER NUMBER” CLIPS> (describe 3.0) “NUMBER” CLIPS> 12.15.7 Calling Shadowed Methods with OverridesThe function override next method is similar to call next method, except that new arguments can be provided. This allows one method to act as a wrapper for another and set up a special environment for the shadowed method. From the set of methods which are more general than the currently executing one, the most specific method which is applicable to the new arguments is executed. (In contrast, call next method calls the next most specific method which is applicable to the same arguments as the currently executing one received.) A recursive call to the generic function itself should be used in lieu of override next method if the most specific of all methods for the generic function which is applicable to the new arguments should be executed. Syntax (override next method <expression>*) Example CLIPS> (clear) CLIPS> (defmethod + ((?a INTEGER) (?b INTEGER)) (override-next-method (* ?a 2) (* ?b 3))) CLIPS> (list-defmethods +) + #2 (INTEGER) (INTEGER) + #SYS1 (NUMBER) (NUMBER) ($? NUMBER) For a total of 2 methods. CLIPS> (preview-generic + 1 2) + #2 (INTEGER) (INTEGER) + #SYS1 (NUMBER) (NUMBER) ($? NUMBER) CLIPS> (watch methods) CLIPS> (+ 1 2) MTH » +:#2 ED:1 (1 2) MTH » +:#SYS1 ED:2 (2 6) MTH « +:#SYS1 ED:2 (2 6) MTH « +:#2 ED:1 (1 2) 8 CLIPS> (unwatch methods) CLIPS> 12.15.8 Calling a Specific MethodThe function call specific method allows the user to call a particular method of a generic function without regards to method precedence. This allows the user to bypass method precedence when absolutely necessary. The method must be applicable to the arguments passed. Shadowed methods can still be called via call next method and override next method. Syntax (call specific method <generic-function> <method-index> <expression>*) Example CLIPS> (clear) CLIPS> (defmethod + ((?a INTEGER) (?b INTEGER)) (* (- ?a ?b) (- ?b ?a))) CLIPS> (list-defmethods +) + #2 (INTEGER) (INTEGER) + #SYS1 (NUMBER) (NUMBER) ($? NUMBER) For a total of 2 methods. CLIPS> (preview-generic + 1 2) + #2 (INTEGER) (INTEGER) + #SYS1 (NUMBER) (NUMBER) ($? NUMBER) CLIPS> (watch methods) CLIPS> (+ 1 2) MTH » +:#2 ED:1 (1 2) MTH « +:#2 ED:1 (1 2) -1 CLIPS> (call-specific-method + 1 1 2) MTH » +:#SYS1 ED:1 (1 2) MTH « +:#SYS1 ED:1 (1 2) 3 CLIPS> (unwatch methods) CLIPS> 12.15.9 Getting the Restrictions of DefmethodsThe function get method restrictions returns a multifield value containing information about the restrictions for the specified method using the following format:
<maximum-number-of-arguments> (can be -1 for wildcards) <number-of-restrictions> <multifield-index-of-first-restriction-info> . . . <multifield-index-of-nth-restriction-info> <first-restriction-query> (TRUE or FALSE) <first-restriction-class-count> <first-restriction-first-class> . . . <first-restriction-nth-class> . . . <mth-restriction-class-count> <mth-restriction-first-class> . . . <mth-restriction-nth-class>
(get method restrictions <generic-function-name> <method-index>) Example CLIPS> (clear) CLIPS> (defmethod foo 50 ((?a INTEGER SYMBOL) (?b (= 1 1)) $?c)) CLIPS> (get-method-restrictions foo 50) (2 -1 3 7 11 13 FALSE 2 INTEGER SYMBOL TRUE 0 FALSE 0) CLIPS> 12.16 CLIPS Object-Oriented Language (COOL) FunctionsThe following functions provide ancillary capabilities for COOL. 12.16.1 Class Functions12.16.1.1 Getting the List of DefclassesThe function get defclass list returns a multifield value containing the names of all defclass constructs visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all defclasses are returned. Syntax (get defclass list [<module-name>]) Example CLIPS> (clear) CLIPS> (get-defclass-list) (FLOAT INTEGER SYMBOL STRING MULTIFIELD EXTERNAL-ADDRESS FACT-ADDRESS INSTANCE-ADDRESS INSTANCE-NAME OBJECT PRIMITIVE NUMBER LEXEME ADDRESS INSTANCE USER INITIAL-OBJECT) CLIPS> (defclass FOO (is-a USER)) CLIPS> (defclass BAR (is-a USER)) CLIPS> (get-defclass-list) (FLOAT INTEGER SYMBOL STRING MULTIFIELD EXTERNAL-ADDRESS FACT-ADDRESS INSTANCE-ADDRESS INSTANCE-NAME OBJECT PRIMITIVE NUMBER LEXEME ADDRESS INSTANCE USER INITIAL-OBJECT FOO BAR) CLIPS> 12.16.1.2 Determining the Module in which a Defclass is DefinedThis function returns the module in which the specified defclass name is defined. Syntax (defclass module <defclass-name>) 12.16.1.3 Determining if a Class ExistsThis function returns the symbol TRUE if the specified class is defined, FALSE otherwise. Syntax (class existp <class-name>) 12.16.1.4 Superclass DeterminationThis function returns the symbol TRUE if the first class is a superclass of the second class, FALSE otherwise. Syntax (superclassp <class1-name> <class2-name>) 12.16.1.5 Subclass DeterminationThis function returns the symbol TRUE if the first class is a subclass of the second class, FALSE otherwise. Syntax (subclassp <class1-name> <class2-name>) 12.16.1.6 Slot ExistenceThis function returns the symbol TRUE if the specified slot is present class, FALSE otherwise. If the inherit keyword is specified then the slot may be inherited, otherwise it must be directly defined in the specified class. Syntax (slot-existp <class> <slot> [inherit]) 12.16.1.7 Testing whether a Slot is WritableThis function returns the symbol TRUE if the specified slot in the specified class is writable (see section 9.3.3.4). Otherwise, it returns the symbol FALSE. An error is generated if the specified class or slot does not exist. Syntax (slot writablep <class-expression> <slot-name-expression>) 12.16.1.8 Testing whether a Slot is InitializableThis function returns the symbol TRUE if the specified slot in the specified class is initializable (see section 9.3.3.4). Otherwise, it returns the symbol FALSE. An error is generated if the specified class or slot does not exist. Syntax (slot initablep <class-expression> <slot-name-expression>) 12.16.1.9 Testing whether a Slot is PublicThis function returns the symbol TRUE if the specified slot in the specified class is public (see section 9.3.3.8). Otherwise, it returns the symbol FALSE. An error is generated if the specified class or slot does not exist. Syntax (slot publicp <class-expression> <slot-name-expression>) 12.16.1.10 Testing whether a Slot can be Accessed DirectlyThis function returns the symbol TRUE if the specified slot in the specified class can be accessed directly (see section 9.3.3.4). Otherwise, it returns the symbol FALSE. An error is generated if the specified class or slot does not exist. Syntax (slot direct accessp <class-expression> <slot-name-expression>) 12.16.1.11 Message handler ExistenceThis function returns the symbol TRUE if the specified message handler is defined (directly only, not by inheritance) for the class, FALSE otherwise. Syntax Defaults are outlined.
<handler-type> ::= around | before | primary | after 12.16.1.12 Determining if a Class can have Direct InstancesThis function returns the symbol TRUE if the specified class is abstract, i.e. the class cannot have direct instances, FALSE otherwise. Syntax (class abstractp <class-name>) 12.16.1.13 Determining if a Class can Satisfy Object PatternsThis function returns the symbol TRUE if the specified class is reactive, i.e. objects of the class can match object patterns, FALSE otherwise. Syntax (class reactivep <class-name>) 12.16.1.14 Getting the List of Superclasses for a ClassThis function groups the names of the direct superclasses of a class into a multifield variable. If the optional argument “inherit” is given, indirect superclasses are also included. A multifield of length zero is returned if an error occurs. Syntax (class superclasses <class-name> [inherit]) Example CLIPS> (class-superclasses INTEGER) (NUMBER) CLIPS> (class-superclasses INTEGER inherit) (NUMBER PRIMITIVE OBJECT) CLIPS> 12.16.1.15 Getting the List of Subclasses for a ClassThis function groups the names of the direct subclasses of a class into a multifield variable. If the optional argument “inherit” is given, indirect subclasses are also included. A multifield of length zero is returned if an error occurs. Syntax (class subclasses <class-name> [inherit]) Example CLIPS> (class-subclasses PRIMITIVE) (NUMBER LEXEME MULTIFIELD EXTERNAL-ADDRESS) CLIPS> (class-subclasses PRIMITIVE inherit) (NUMBER INTEGER FLOAT LEXEME SYMBOL STRING MULTIFIELD ADDRESS EXTERNAL-ADDRESS FACT-ADDRESS INSTANCE-ADDRESS INSTANCE INSTANCE-NAME) CLIPS> 12.16.1.16 Getting the List of Slots for a ClassThis function groups the names of the explicitly defined slots of a class into a multifield variable. If the optional argument “inherit” is given, inherited slots are also included. A multifield of length zero is returned if an error occurs. Syntax (class slots <class-name> [inherit]) Example CLIPS> (defclass A (is-a USER) (slot x)) CLIPS> (defclass B (is-a A) (slot y)) CLIPS> (class-slots B) (y) CLIPS> (class-slots B inherit) (x y) CLIPS> 12.16.1.17 Getting the List of Message Handlers for a ClassThis function groups the class names, message names and message types of the message handlers attached direct to class into a multifield variable (implicit slot accessors are not included). If the optional argument “inherit” is given, inherited message handlers are also included. A multifield of length zero is returned if an error occurs. Syntax (get defmessage handler list <class-name> [inherit]) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER)) CLIPS> (defmessage-handler A foo ()) CLIPS> (get-defmessage-handler-list A) (A foo primary) CLIPS> (get-defmessage-handler-list A inherit) (USER init primary USER delete primary USER create primary USER print primary USER direct-modify primary USER message-modify primary USER direct-duplicate primary USER message-duplicate primary A foo primary) CLIPS> 12.16.1.18 Getting the List of Facets for a SlotThis function returns a multifield listing the facet values for the specified slot (the slot can be inherited or explicitly defined for the class). A multifield of length zero is returned if an error occurs. Following is a table indicating what each field represents and its possible values:
Syntax (slot facets <class-name> <slot-name>) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot x (access read-only))) CLIPS> (defclass B (is-a A) (multislot y)) CLIPS> (slot-facets B x) (SGL STC INH R LCL RCT EXC PRV NIL NIL) CLIPS> (slot-facets B y) (MLT STC INH RW LCL RCT EXC PRV NIL put-y) CLIPS> 12.16.1.19 Getting the List of Source Classes for a SlotThis function groups the names of the classes which provide facets for a slot of a class into a multifield variable. In the case of an exclusive slot, this multifield will be of length one and contain the name of the contributing class. However, composite slots may have facets from many different classes (see section 9.3.3.6). A multifield of length zero is returned if an error occurs. Syntax (slot sources <class-name> <slot-name>) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot x (access read-only))) CLIPS> (defclass B (is-a A) (slot x (source composite) (default 100))) CLIPS> (defclass C (is-a B)) CLIPS> (slot-sources A x) (A) CLIPS> (slot-sources B x) (A B) CLIPS> (slot-sources C x) (A B) CLIPS> 12.16.1.20 Getting the Primitive Types for a SlotThis function groups the names of the primitive types allowed for a slot into a multifield variable. A multifield of length zero is returned if an error occurs. Syntax (slot types <class-name> <slot-name>) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot y (type INTEGER LEXEME))) CLIPS> (slot-types A y) (INTEGER SYMBOL STRING) CLIPS> 12.16.1.21 Getting the Cardinality for a SlotThis function groups the minimum and maximum cardinality allowed for a multifield slot into a multifield variable. A maximum cardinality of infinity is indicated by the symbol +oo (the plus character followed by two lowercase o’s—not zeroes). A multifield of length zero is returned for single field slots or if an error occurs. Syntax (slot cardinality <class-name> <slot-name>) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot x) (multislot y (cardinality ?VARIABLE 5)) (multislot z (cardinality 3 ?VARIABLE))) CLIPS> (slot-cardinality A x) () CLIPS> (slot-cardinality A y) (0 5) CLIPS> (slot-cardinality A z) (3 +oo) CLIPS> 12.16.1.22 Getting the Allowed Values for a SlotThis function groups the allowed values for a slot (specified in any of allowed … facets for the slots) into a multifield variable. If no allowed … facets were specified for the slot, then the symbol FALSE is returned. A multifield of length zero is returned if an error occurs. Syntax (slot allowed values <class-name> <slot-name>) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot x) (slot y (allowed-integers 2 3) (allowed-symbols foo))) CLIPS> (slot-allowed-values A x) FALSE CLIPS> (slot-allowed-values A y) (2 3 foo) CLIPS> 12.16.1.23 Getting the Numeric Range for a SlotThis function groups the minimum and maximum numeric ranges allowed a slot into a multifield variable. A minimum value of infinity is indicated by the symbol oo (the minus character followed by two lowercase o’s—not zeroes). A maximum value of infinity is indicated by the symbol +oo (the plus character followed by two lowercase o’s—not zeroes). The symbol FALSE is returned for slots in which numeric values are not allowed. A multifield of length zero is returned if an error occurs. Syntax (slot range <class-name> <slot-name>) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot x) (slot y (type SYMBOL)) (slot z (range 3 10))) CLIPS> (slot-range A x) (-oo +oo) CLIPS> (slot-range A y) FALSE CLIPS> (slot-range A z) (3 10) CLIPS> 12.16.1.24 Getting the Default Value for a SlotThis function returns the default value associated with a slot. If a slot has a dynamic default, the expression will be evaluated when this function is called. The symbol FALSE is returned if an error occurs. Syntax (slot default-value <class-name> <slot-name>) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (slot x (default 3)) (multislot y (default a b c)) (slot z (default-dynamic (gensym)))) CLIPS> (slot-default-value A x) 3 CLIPS> (slot-default-value A y) (a b c) CLIPS> (slot-default-value A z) gen1 CLIPS> (slot-default-value A z) gen2 CLIPS> 12.16.1.25 Setting the Defaults Mode for ClassesThis function sets the defaults mode used when classes are defined. The old mode is the return value of this function. Syntax (set class-defaults-mode <mode>)
12.16.1.26 Getting the Defaults Mode for ClassesThis function returns the current defaults mode used when classes are defined (convenience or conservation). Syntax (get class-defaults-mode) 12.16.2 Message handler Functions12.16.2.1 Existence of Shadowed HandlersThis function returns the symbol TRUE if there is another message handler available for execution, FALSE otherwise. If this function is called from an around handler and there are any shadowed handlers (see section 9.5.3), the return value is the symbol TRUE. If this function is called from a primary handler and there are any shadowed primary handlers, the return value is the symbol TRUE. In any other circumstance, the return value is the symbol FALSE. Syntax (next handlerp) 12.16.2.2 Calling Shadowed HandlersIf the conditions are such that the function next handlerp would return the symbol TRUE, then calling this function will execute the shadowed method. Otherwise, a message execution error (see section 9.5.4) will occur. In the event of an error, the return value of this function is the symbol FALSE, otherwise it is the return value of the shadowed handler. The shadowed handler is passed the same arguments as the calling handler.
Syntax (call next handler) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete)) CLIPS> (defmessage-handler A print-args ($?any) (printout t “A: ” ?any crlf) (if (next-handlerp) then (call-next-handler))) CLIPS> (defmessage-handler USER print-args ($?any) (printout t “USER: ” ?any crlf)) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] print-args 1 2 3 4) A: (1 2 3 4) USER: (1 2 3 4) CLIPS> 12.16.2.3 Calling Shadowed Handlers with Different ArgumentsThis function is identical to call next handler except that this function can change the arguments passed to the shadowed handler. Syntax (override next handler <expression>*) Example CLIPS> (clear) CLIPS> (defclass A (is-a USER) (role concrete)) CLIPS> (defmessage-handler A print-args ($?any) (printout t “A: ” ?any crlf) (if (next-handlerp) then (override-next-handler (rest$ ?any)))) CLIPS> (defmessage-handler USER print-args ($?any) (printout t “USER: ” ?any crlf)) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] print-args 1 2 3 4) A: (1 2 3 4) USER: (2 3 4) CLIPS> 12.16.3 Definstances Functions12.16.3.1 Getting the List of DefinstancesThe function get definstances list returns a multifield value containing the names of all definstances constructs visible to the module specified by <module-name> or to the current module if none is specified. If * is specified as the module name, then all definstances are returned. Syntax (get definstances list [<module-name>]) Example CLIPS> (clear) CLIPS> (get-definstances-list) () CLIPS> (definstances foo) CLIPS> (definstances bar) CLIPS> (get-definstances-list) (foo bar) CLIPS> 12.16.3.2 Determining the Module in which a Definstances is DefinedThis function returns the module in which the specified definstances name is defined. Syntax (definstances module <definstances-name>) 12.16.4 Instance Manipulation Functions and Actions12.16.4.1 Initializing an InstanceThis function implements the init message handler attached to the class USER (see section 9.4.5.1). This function evaluates and places slot expressions given by the class definition that were not specified by slot overrides in the call to make instanceor initialize instance (see section 9.6.1). This function should never be called directly unless an init message handler is being defined such that the one attached to USER will never be called. However, such a definition is unusual and recommended only to advanced users. A user defined class which does not inherit indirectly or directly from the class USER will require an init message handler which calls this function in order for instances of the class to be created. If this function is called from an init message within the context of a make instance or initialize instance call and there are no errors in evaluating the class defaults, this function will return the address of the instance it is initializing. Otherwise, this function will return the symbol FALSE. Syntax (init slots) 12.16.4.2 Deleting an InstanceThis function deletes the specified instances by sending them a delete message. The argument can be one or more instance names, instance addresses, or symbols (an instance name without enclosing brackets). The instance specified by the arguments must exist (except in the case of “*”). If “*” is specified for the instance, all instances will be sent the delete message (unless there is an instance named “*”). This function returns the symbol TRUE if all instances were successfully deleted, otherwise it returns the symbol FALSE. Note, this function is exactly equivalent to sending the instance(s) the delete message directly and is provided only as an intuitive counterpart to the function retract for facts. Syntax (unmake instance <instance-expression>+) 12.16.4.3 Deleting the Active Instance from a HandlerThis function operates implicitly on the active instance (see section 9.4.1.1) for a message, and thus can only be called from within the body of a message handler. This function directly deletes the active instance and is the one used to implement the delete handler attached to class USER (see section 9.4.5.2). This function returns the symbol TRUE if the instance was successfully deleted, otherwise the symbol FALSE. Syntax (delete instance) 12.16.4.4 Determining the Class of an ObjectThis function returns a symbol which is the name of the class of its argument. It returns the symbol FALSE on errors. This function is equivalent to the type function (see section 12.15.4). Syntax (class <object-expression>) Example CLIPS> (class 34) INTEGER CLIPS> 12.16.4.5 Determining the Name of an InstanceThis function returns a symbol which is the name of its instance argument. It returns the symbol FALSE on errors. The evaluation of the argument must be an instance name or instance address of an existing instance. Syntax (instance name <instance-expression>) 12.16.4.6 Determining the Address of an InstanceThis function returns the address of its instance argument. It returns the symbol FALSE on errors. The evaluation of <instance expression> must be an instance name or instance address of an existing instance. If <module> or * is not specified, the function searches only in the current module. If * is specified, the current module and imported modules are recursively searched. If <module> is specified, only that module is searched. The :: syntax cannot be used with the instance name if <module> or * is specified. Syntax (instance address [<module> | *] <instance-expression>) 12.16.4.7 Converting a Symbol to an Instance NameThis function returns an instance name which is equivalent to its symbol argument. It returns the symbol FALSE on errors. Syntax (symbol to instance name <symbol-expression>) Example CLIPS> (symbol-to-instance-name (sym-cat abc def)) [abcdef] CLIPS> 12.16.4.8 Converting an Instance Name to a SymbolThis function returns a symbol which is equivalent to its instance name argument. It returns the symbol FALSE on errors. Syntax (instance name to symbol <instance-name-expression>) Example CLIPS> (instance-name-to-symbol [a]) a CLIPS> 12.16.4.9 Predicate Functions12.16.4.9.1 Testing for an Instance
Syntax (instancep <expression>) 12.16.4.9.2 Testing for an Instance AddressThis function returns the symbol TRUE if the evaluation of its argument is an instance address. Otherwise, it returns the symbol FALSE. Syntax (instance addressp <expression>) 12.16.4.9.3 Testing for an Instance NameThis function returns the symbol TRUE if the evaluation of its argument is an instance name. Otherwise, it returns the symbol FALSE. Syntax (instance namep <expression>) 12.16.4.9.4 Testing for the Existence an InstanceThis function returns the symbol TRUE if the specified instance exists. Otherwise, it returns the symbol FALSE. If the argument is an instance name, the function determines if an instance of the specified name exists. If the argument is an instance address, the function determines if the specified address is still valid. Syntax (instance existp <instance-expression>) 12.16.4.10 Reading a Slot ValueThis function returns the value of the specified slot of the active instance (see section 9.4.1.1). If the slot does not exist, the slot does not have a value or this function is called from outside a message handler, this function will return the symbol FALSE and an error will be generated. This function differs from the ?self:<slot name> syntax in that the slot is not looked up until the function is actually called. Thus it is possible to access different slots every time the function is executed (see section 9.4.2 for more detail). This function bypasses message passing. Syntax (dynamic get <slot-name-expression>) 12.16.4.11 Setting a Slot ValueThis function sets the value of the specified slot of the active instance (see section 9.4.1.1). If the slot does not exist, there is an error in evaluating the arguments to be placed or this function is called from outside a message handler, this function will return the symbol FALSE and an error will be generated. Otherwise, the new slot value is returned. This function differs from the (bind ?self:<slot name> <value>*) syntax in that the slot is not looked up until the function is actually called. Thus it is possible to access different slots every time the function is executed (see section 9.4.2 for more detail). This function bypasses message passing. Syntax (dynamic put <slot-name-expression> <expression>*) 12.16.4.12 Multifield Slot FunctionsThe following functions allow convenient manipulation of multifield slots. There are three types of functions: replacing a range of fields with one or more new values, inserting one or more new values at an arbitrary point, and deleting a range of fields. For each type, there are two forms of functions: an external interface which sets the new value for the multifield slot with a put message (see section 9.3.3.9), and an internal interface that can only be called from message handlers which sets the slot for the active instance (see section 9.4.1.1) directly. Both forms read the original value of the slot directly without the use of a get message. All of these functions return the new slot value on success and the symbol FALSE on errors. 12.16.4.12.1 Replacing FieldsAllows the replacement of a range of fields in a multifield slot value with one or more new values. The range indices must be from 1..n, where n is the number of fields in the multifield slot’s original value and n > 0. External Interface Syntax (slot replace$ <instance-expression> <mv-slot-name> <range-begin> <range-end> <expression>+) Internal Interface Syntax (slot-direct replace$ <mv-slot-name> <range-begin> <range-end> <expression>+) Example CLIPS> (defclass A (is-a USER) (role concrete) (multislot mfs (default a b c d e) (create-accessor write))) CLIPS> (make-instance a of A) [a] CLIPS> (slot-replace$ a mfs 2 4 2 3 4) (a 2 3 4 e) CLIPS> 12.16.4.12.2 Inserting FieldsAllows the insertion of one or more new values in a multifield slot value before a specified field index. The index must greater than or equal to 1. A value of 1 inserts the new value(s) at the beginning of the slot’s value. Any value greater than the length of the slot’s value appends the new values to the end of the slot’s value. External Interface Syntax (slot insert$ <instance-expression> <mv-slot-name> <index> <expression>+) Internal Interface Syntax (slot-direct insert$ <mv-slot-name> <index> <expression>+) Example CLIPS> (initialize-instance a) [a] CLIPS> (slot-insert$ a mfs 2 4 2 3 4) (a 4 2 3 4 b c d e) CLIPS> 12.16.4.12.3 Deleting FieldsAllows the deletion of a range of fields in a multifield slot value. The range indices must be from 1..n, where n is the number of fields in the multifield slot’s original value and n > 0. External Interface Syntax (slot delete$ <instance-expression> <mv-slot-name> <range-begin> <range-end>) Internal Interface Syntax (slot-direct delete$ <mv-slot-name> <range-begin> <range-end>) Example CLIPS> (initialize-instance a) [a] CLIPS> (slot-delete$ a mfs 2 4) (a e) CLIPS> 12.17 Defmodule FunctionsThe following functions provide ancillary capabilities for the defmodule construct. 12.17.1 Getting the List of DefmodulesThe function get defmodule list returns a multifield value containing the names of all defmodules that are currently defined. Syntax (get defmodule list) Example CLIPS> (clear) CLIPS> (get-defmodule-list) (MAIN) CLIPS> (defmodule A) CLIPS> (defmodule B) CLIPS> (get-defmodule-list) (MAIN A B) CLIPS> 12.17.2 Setting the Current ModuleThis function sets the current module. It returns the name of the previous current module. If an invalid module name is given, then the current module is not changed and the name of the current module is returned. Syntax (set current module <defmodule-name>) 12.17.3 Getting the Current ModuleThis function returns the name of the current module. Syntax (get current module) 12.18 Sequence ExpansionIn the past, there has been no distinction between single field and multifield variable references within function calls (as opposed to declaring variables for function parameters or variables used for pattern matching). For example, for the rule: (defrule expansion (foo $?b) ⇒ (printout t ?b crlf) (printout t $?b crlf))
<Fact-0> CLIPS> (run) (a b c) (a b c) CLIPS>
<Fact-0> CLIPS> (run) (a b c) abc CLIPS>
(printout t a b c crlf)
CLIPS> (defglobal ?*x* = (create$ 3 4 5)) CLIPS> (+ ?*x*) ERROR: Function + expected at least 2 argument(s) CLIPS> (+ $?*x*) 12 CLIPS>
(str-cat $?any))
12.18.1 Sequence Expansion and RulesSequence expansion is allowed on the LHS of rules, but only within function calls. If a variable is specified in a pattern as a single or multifield variable, then all other references to that variable that are not within function calls must also be the same. For example, the following rule is not allowed
(pattern $?x ?x $?x) ⇒)
(pattern $?x&:(> (length$ ?x) 1)) (another-pattern $?y&:(> (length$ ?y) 1)) (test (> (+ $?x) (+ $?y))) ⇒)
12.18.2 Multifield Expansion FunctionThe $ operator is merely a shorthand notation for the expand$ function call. For example, the function calls
Syntax (expand$ <multifield-expression>)
12.18.3 Setting The Sequence Operator Recognition BehaviorThis function sets the sequence operator recognition behavior. When this behavior is disabled (FALSE by default), multifield variables found in function calls are treated as a single argument. When this behaviour is enabled, multifield variables are expanded and passed as separate arguments in the function call. This behavior should be set before an expression references a multifield variable is encountered (i.e. changing the behavior does not retroactively change the behavior for previously encountered expressions). The return value for this function is the old value for the behavior. Syntax (set sequence operator recognition <boolean-expression>) 12.18.4 Getting The Sequence Operator Recognition BehaviorThis function returns the current value of the sequence operator recognition behavior (TRUE or FALSE). Syntax (get sequence operator recognition) 12.18.5 Sequence Operator CaveatCLIPS normally tries to detect as many constraint errors as possible for a function call at parse time, such as bad number of arguments or types. However, if the sequence expansion operator is used in the function call, all such checking is delayed until run time (because the number and types of arguments can change for each execution of the call.) For example:
CLIPS> (deffunction bar ($?a) (foo ?a)) ERROR: Function foo expected exactly 2 argument(s)
(deffunction bar ($?a) (foo ?a) CLIPS> (deffunction bar ($?a) (foo $?a)) CLIPS> (bar 1) ERROR: Function foo expected exactly 2 argument(s) FALSE CLIPS> (bar 1 2) FALSE CLIPS> Section 13 CommandsThis section describes commands primarily intended for use from the top level command prompt. These commands may also be used from constructs and other places where functions can be used. 13.1 Environment CommandsThe following commands control the CLIPS environment. 13.1.1 Loading Constructs From A File.Loads the constructs stored in the file specified by <file name> into the environment. If the compilations item is being watched (see section 13.2), then an informational message (including the type and name of the construct) will be displayed for each construct loaded. If the compilations item is not being watched, then a character is printed for each construct loaded (“*” for defrule, “$” for deffacts, “%” for deftemplate, “:” for defglobal, “!” for deffunction, “^” for defgeneric, “&” for defmethod, “#” for defclass, “~” for defmessage handler, “@” for definstances, and “+” for defmodule). This function returns TRUE if the file was successfully loaded, otherwise FALSE is returned. Syntax (load <file-name>) 13.1.2 Loading Constructs From A File without Progress InformationLoads the constructs stored in the file specified by <file name> into the environment, however, unlike the load command informational messsages are not printed to show the progress of loading the file. Error messages are still printed if errors are encountered while loading the file. This function returns TRUE if the file was successfully loaded, otherwise FALSE is returned. Syntax (load* <file-name>) 13.1.3 Saving All Constructs To A FileSaves all of the constructs (defrules, deffacts, deftemplates, etc.) in the current environment into the file specified by <file name>. Note that deffunctions and generic functions are saved twice to the file. Because it is possible to create circular references among deffunctions and generic functions by redefining them, a forward declaration (containing no actions) of the functions is saved first to the file, and then the actual declaration (containing the actions) is saved. This function returns TRUE if the file was successfully saved, otherwise FALSE is returned. This function uses the pretty print forms of the constructs. If pretty printing has been disabled by the conserve mem command, then the save command will have no output. Syntax (save <file-name>) 13.1.4 Loading a Binary ImageLoads the constructs stored in the binary file specified by <file name> into the environment. The specified file must have been created by bsave. Loading a binary image is quicker than using the load command to load a ASCII text file. A bload clears all constructs from the current CLIPS environment (as well as all facts and instances). Bload can be called at any time unless some constructs that bload will affect are in use (e.g. a deffunction is currently executing). The only constructive/destructive operation that can occur after a bload is the clear command or the bload command (which clears the current binary image). This means that constructs cannot be loaded or deleted while a bload is in effect. In order to add constructs to a binary image, the original ASCII text file must be reloaded, the new constructs added, and then another bsave must be performed. This function returns TRUE if the file was successfully bloaded, otherwise FALSE is returned.
Syntax (bload <file-name>) 13.1.5 Saving a Binary ImageSaves all of the constructs in the current environment into the file specified by <file name>. The save file is written using a binary format which results in faster load time. The save file must be loaded via the bload command. A bsave may be performed at any time (except when a bload is in effect). The pretty print representation of a construct is not saved with a binary image (thus, commands like ppdefrule will show no output for any of the rules associated with the binary image). In addition, constraint information associated with constructs is not saved to the binary image unless dynamic constraint checking is enabled (using the set dynamic constraint checking command). This function returns TRUE if the file was successfully bsaved, otherwise FALSE is returned. Syntax (bsave <file-name>) 13.1.6 Clearing CLIPSClears CLIPS. Removes all constructs and all associated data structures (such as facts and instances) from the CLIPS environment. A clear may be performed safely at any time, however, certain constructs will not allow themselves to be deleted while they are in use. For example, while deffacts are being reset (by the reset command), it is not possible to remove them using the clear command. Note that the clear command does not effect many environment characteristics (such as the current conflict resolution strategy). This function has no return value. Syntax (clear) 13.1.7 Exiting CLIPSQuits CLIPS. This function has no return value. Syntax (exit [<integer-expression>])
13.1.8 Resetting CLIPSResets CLIPS. Removes all activations from the agenda, all facts from the fact list and all instances of user defined classes, then assigns global variables their initial values, asserts all facts listed in deffacts statements into the fact list, creates all instances listed in definstances statements, sets the current module to the MAIN module and automatically focuses on the same module. Incremental reset is supported for rules. This means that rules can be activated from facts that were asserted before the rule was defined without performing a reset. A reset can be performed while rules are executing. Note that the reset command does not effect many environment characteristics (such as the current conflict resolution strategy). This function has no return value. Syntax (reset) 13.1.9 Executing Commands From a FileAllows “batch” processing of CLIPS interactive commands by replacing standard input with the contents of a file. Any command or function can be used in a batch file, as well as construct definitions and responses to read or readline function calls. The load command should be used in batch files rather than defining constructs directly. The load command expects only constructs and hence moves to the next construct when an error occurs. The batch command, however, moves on until it finds the next construct or command (and in the case of a construct this is likely to generate more errors as the remaining commands and functions in the construct are parsed). This function returns TRUE if the batch file was successfully executed, otherwise FALSE is returned. Note that the batch command operates by replacing standard input rather than by immediately executing the commands found in the batch file. In effect, if you execute a batch command from the RHS of a rule, the commands in that batch file will not be processed until control is returned to the top level prompt. Syntax (batch <file-name>)
13.1.10 Executing Commands From a File Without Replacing Standard InputEvaluates the series of commands stored in the file specified by <file name>. Unlike the batch command, batch* evaluates all of the commands in the specified file before returning. The batch* command does not replace standard input and thus a batch* file cannot be used to provide input to functions such as read and readline. In addition, commands stored in the batch* file and the return value of these commands are not echoed to standard output.
Syntax (batch* <file-name>) 13.1.11 Determining CLIPS Compilation OptionsGenerates a textual description of the settings of the CLIPS compiler flags. This function has no return value. Syntax (options) 13.1.12 Calling the Operating SystemThe system function allows a call to the operating system. It is patterned after the system function provided to C on most UNIX systems. This function has no return value. Syntax (system <lexeme-expression>*) Example
(defrule print-directory
Not all operating systems/compilers provide this function. The code is stored in the sysdep.c file, and the default coding for generic CLIPS is a nonfunctional stub that will compile on any machine. On some machines (such as an IBM PC running DOS), there may be insufficient memory available to spawn a subprocess to execute the system command. In such a case, the command will not be executed and the system command will return with no action taken. 13.1.13 Setting The Auto Float Dividend BehaviorThis function sets auto float dividend behavior. When this behavior is enabled (TRUE by default) the dividend of the division function is automatically converted to a floating point number. The return value for this function is the old value for the behavior. Syntax (set auto float dividend <boolean-expression>) 13.1.14 Getting The Auto Float Dividend BehaviorThis function returns the current value of the auto float dividend behavior (TRUE or FALSE). Syntax (get auto float dividend) 13.1.15 Setting the Dynamic Constraint Checking BehaviorThis function sets dynamic constraint checking behavior. When this behavior is disabled (FALSE by default), newly created data objects (such as deftemplate facts and instances) do not have their slot values checked for constraint violations. When this behavior is enabled (TRUE), the slot values are checked for constraint violations. The return value for this function is the old value for the behavior. Constraint information is not saved when using the bload and constructs to c command if dynamic constraint checking is disabled. Syntax (set dynamic constraint checking <boolean-expression>) 13.1.16 Getting the Dynamic Constraint Checking BehaviorThis function returns the current value of the dynamic constraint checking behavior (TRUE or FALSE). Syntax (get dynamic constraint checking) 13.1.17 Setting the Static Constraint Checking BehaviorThis function sets static constraint checking behavior. When this behavior is disabled (FALSE), constraint violations are not checked when function calls and constructs are parsed. When this behavior is enabled (TRUE by default), constraint violations are checked when function calls and constructs are parsed. The return value for this function is the old value for the behavior. Syntax (set static constraint checking <boolean-expression>) 13.1.18 Getting the Static Constraint Checking BehaviorThis function returns the current value of the static constraint checking behavior (TRUE or FALSE). Syntax (get static constraint checking) 13.1.19 Finding SymbolsThis command displays all symbols currently defined in CLIPS which contain a specified substring. This command has no return value. Syntax (apropos <lexeme>) Example CLIPS> (apropos pen) dependents mv-append open dependencies CLIPS>
If the ANSI_COMPILER flag has been set to 0, then apropos only shows those symbols that begin with the specified substring. 13.2 Debugging CommandsThe following commands control the CLIPS debugging features. 13.2.1 Generating Trace FilesSends all information normally sent to the logical names wclips,wdialog, wdisplay, werror, wwarning,wtrace, and stdout to <file name> as well as to their normal destination. Additionally, all information received from logical name stdin is also sent to <file name> as well as being returned by the requesting function. This function returns TRUE if the dribble file was successfully opened, otherwise FALSE is returned. Syntax (dribble on <file-name>) 13.2.2 Closing Trace FilesStops sending trace information to the dribble file. This function returns TRUE if the dribble file was successfully closed, otherwise FALSE is returned. Syntax (dribble off) 13.2.3 Enabling Watch ItemsThis function causes messages to be displayed when certain CLIPS operations take place. Syntax (watch <watch-item>)
compilations | statistics | focus | messages | deffunctions <deffunction-name>* | globals <global-name>* | rules <rule-name>* | activations <rule-name>* | facts <deftemplate-name>* | instances <class-name>* | slots <class-name>* | message-handlers <handler-spec-1>* [<handler-spec-2>]) | generic-functions <generic-name>* | methods <method-spec-1>* [<method-spec-2>]
<handler-name> <handler-type> <handler-spec-2> ::= <class-name> [<handler-name> [<handler-type>]]
<method-spec-2> ::= <generic-name> [<method-index>]
Example CLIPS> (watch rules) CLIPS> 13.2.4 Disabling Watch ItemsThis function disables the effect of the watch command. Syntax (unwatch watch-item>)
Example CLIPS> (unwatch all) CLIPS> 13.2.5 Viewing the Current State of Watch ItemsThis command displays the current state of watch items. Syntax (list watch items [<watch-item>])
Example CLIPS> (list-watch-items) facts = off instances = off slots = off rules = off activations = off messages = off message-handlers = off generic-functions = off methods = off deffunctions = off compilations = on statistics = off globals = off focus = off CLIPS> (list-watch-items facts) facts = off MAIN: initial-fact = off CLIPS> 13.3 Deftemplate CommandsThe following commands manipulate deftemplates. 13.3.1 Displaying the Text of a DeftemplateDisplays the text of a given deftemplate. This function has no return value. Syntax (ppdeftemplate <deftemplate-name>) 13.3.2 Displaying the List of DeftemplatesDisplays the names of all deftemplates. This function has no return value. Syntax (list deftemplates [<module-name>])
13.3.3 Deleting a DeftemplateThis function deletes a previously defined deftemplate. Syntax (undeftemplate <deftemplate-name>)
13.4 Fact CommandsThe following commands display information about facts. 13.4.1 Displaying the Fact-ListDisplays facts stored in the fact list. Syntax (facts [<module-name>] [<start-integer-expression> [<end-integer-expression> [<max-integer-expression>]]])
13.4.2 Loading Facts From a FileThis function will assert a file of information as facts into the CLIPS fact list. It can read files created with save facts or any ASCII text file. Each fact should begin with a left parenthesis and end with a right parenthesis. Facts may span across lines and can be written in either ordered or deftemplate format. This function returns TRUE if the fact file was successfully loaded, otherwise FALSE is returned. Syntax (load facts <file-name>) 13.4.3 Saving The Fact-List To A FileThis function saves all of the facts in the current fact list into the file specified by <file name>. External address and fact address fields are saved as strings. Instance address fields are converted to instance names. Optionally, the scope of facts to be saved can be specified. If <save scope> is the symbol visible, then all facts visible to the current module are saved. If <save scope> is the symbol local, then only those facts with deftemplates defined in the current module are saved. If <save scope> is not specified, it defaults to local. If <save scope> is specified, then one or more deftemplate names may also be specified. In this event, only those facts with associated with a corresponding deftemplate in the specified list will be saved. This function returns TRUE if the fact file was successfully saved, otherwise FALSE is returned. Syntax (save facts <file-name> [<save-scope> <deftemplate-names>*]) <save-scope> ::= visible | local 13.4.4 Setting the Duplication Behavior of FactsThis function sets fact duplication behavior. When this behavior is disabled (FALSE by default), asserting a duplicate of a fact already in the fact list produces no effect. When enabled (TRUE), the duplicate fact is asserted with a new fact index. The return value for this function is the old value for the behavior. Syntax (set fact duplication <boolean-expression>)
CLIPS> (get-fact-duplication) FALSE CLIPS> (watch all) CLIPS> (assert (a)) ==> f-0 (a) <Fact-0> CLIPS> (assert (a)) FALSE CLIPS> (set-fact-duplication TRUE) FALSE CLIPS> (assert (a)) ==> f-1 (a) <Fact-1> CLIPS> 13.4.5 Getting the Duplication Behavior of FactsThis function returns the current value of the fact duplication behavior (TRUE or FALSE). Syntax (get fact duplication)
13.5 Deffacts CommandsThe following commands manipulate deffacts. 13.5.1 Displaying the Text of a DeffactsDisplays the text of a given deffacts. This function has no return value. Syntax (ppdeffacts <deffacts-name>) 13.5.2 Displaying the List of DeffactsDisplays the names of all deffacts stored in the CLIPS environment. Syntax (list deffacts [<module-name>])
13.5.3 Deleting a DeffactsThis function deletes a previously defined deffacts. Syntax (undeffacts <deffacts-name>)
13.6 Defrule CommandsThe following commands manipulate defrules. 13.6.1 Displaying the Text of a RuleDisplays the text of a given rule. Syntax (ppdefrule <rule-name>)
13.6.2 Displaying the List of RulesDisplays the names of all rules stored in the CLIPS environment. Syntax (list defrules [<module-name>])
13.6.3 Deleting a DefruleThis function deletes a previously defined defrule. Syntax (undefrule <defrule-name>)
13.6.4 Displaying Matches for a RuleFor a specified rule, displays the list of the facts or instances which match each pattern in the rule’s LHS, the partial matches for the rule, and the activations for the rule. Note that the patterns for which information is displayed include the patterns added or rearranged by CLIPS (see section 5.4.9). When listed as a partial match, the not, exists, and forall CEs are shown as a comma with no following pattern entity identifier (such as a fact-index or instance name). Other CEs contained within these CEs are not displayed as part of the information shown for a partial match. This function has no return value. Syntax (matches <rule-name>) Example The rule matches-example-1 has three patterns and none are added by CLIPS. Fact f-1 matches the first pattern, facts f-2 and f-3 match the the second pattern, and fact f-4 matches the third pattern. Issuing the run command will remove all of the rule’s activations from the agenda.
CLIPS> (defrule matches-example-1 (a ?) (b ?) (c ?) ⇒) CLIPS> (reset) CLIPS> (assert (a 1) (b 1) (b 2) (c 1)) <Fact-4> CLIPS> (facts) f-0 (initial-fact) f-1 (a 1) f-2 (b 1) f-3 (b 2) f-4 (c 1) For a total of 5 facts. CLIPS> (run) CLIPS>
(defrule matches-example-2 (not (d ?)) (exists (b ?x) (c ?x)) ⇒) CLIPS>
Matches for Pattern 1 f-1 Matches for Pattern 2 f-2 f-3 Matches for Pattern 3 f-4 Partial matches for CEs 1 - 2 f-1,f-3 f-1,f-2 Partial matches for CEs 1 - 3 f-1,f-2,f-4 f-1,f-3,f-4 Activations None CLIPS>
Matches for Pattern 1 f-0 Matches for Pattern 2 None Matches for Pattern 3 f-2 f-3 Matches for Pattern 4 f-4 Partial matches for CEs 1 - 2 f-0, Partial matches for CEs 1 - 3 f-0,, Activations f-0,, CLIPS> 13.6.5 Setting a Breakpoint for a RuleSets a breakpoint for a given rule. Syntax (set break <rule-name>)
13.6.6 Removing a Breakpoint for a RuleRemoves a breakpoint for a given rule. Syntax (remove break [<defrule-name>])
13.6.7 Displaying Rule BreakpointsThis command displays all the rules which have breakpoints set. This function has no return value. Syntax (show breaks [<module-name>])
13.6.8 Refreshing a RulePlaces all current activations of a given rule on the agenda. This function has no return value. Syntax (refresh <rule-name>) 13.6.9 Setting the Incremental Reset BehaviorThis function sets the incremental reset behavior. When this behavior is enabled (TRUE by default), newly defined rules are updated based upon the current state of the fact list. When disabled (FALSE), newly defined rules are only updated by facts added after the rule is defined. In order to prevent rules from obtaining an inconsistent state, the incremental reset behavior can only be changed when there are no rules currently defined. The return value for this function is the old value for the behavior. Syntax (set incremental reset <boolean-expression>) 13.6.10 Getting the Incremental Reset BehaviorThis function returns the current value of the incremental reset behavior (TRUE or FALSE). Syntax (get incremental reset) 13.6.11 Determining the Logical Dependencies of a Pattern EntityThe dependencies function lists the partial matches from which a pattern entity receives logical support. This function has no return value. Syntax (dependencies <fact-or-instance-specifier>)
Example
(defrule list-dependencies 13.6.12 Determining the Logical Dependents of a Pattern EntityThe dependents function lists all pattern entities which receive logical support from a pattern entity. This function has no return value. Syntax (dependents <fact-or-instance-specifier>)
Example
(defrule list-dependents 13.7 Agenda CommandsThe following commands manipulate agenda. 13.7.1 Displaying the AgendaDisplays all activations on the agenda. This function has no return value. Syntax (agenda [<module-name>])
13.7.2 Running CLIPSStarts execution of the rules. If the optional first argument is positive, execution will cease after the specified number of rule firings or when the agenda contains no rule activations. If there are no arguments or the first argument is a negative integer, execution will cease when the agenda contains no rule activations. If the focus stack is empty, then the MAIN module is automatically becomes the current focus. The run command has no additional effect if evaluated while rules are executing. Note that the number of rules fired and timing information is no longer printed after the completion of the run command unless the statistics item is being watched (see section 13.2). If the rules item is being watched, then an informational message will be printed each time a rule is fired. This function has no return value. Syntax (run [<integer-expression>]) 13.7.3 Focusing on a Group of RulesPushes one or more modules onto the focus stack. The specified modules are pushed onto the focus stack in the reverse order they are listed. The current module is set to the last module pushed onto the focus stack. The current focus is the top module of the focus stack. Thus (focus A B C) pushes C, then B, then A unto the focus stack so that A is now the current focus. Note that the current focus is different from the current module. Focusing on a module implies “remembering” the current module so that it can be returned to later. Setting the current module with the set current module function changes it without remembering the old module. Before a rule executes, the current module is changed to the module in which the executing rule is defined (the current focus). This function returns a boolean value: FALSE if an error occurs, otherwise TRUE. Syntax (focus <module-name>+) 13.7.4 Stopping Rule ExecutionThe halt function may be used on the RHS of a rule to prevent further rule firing. It is called without arguments. After halt is called, control is returned from the run command. The agenda is left intact, and execution may be continued with a run command. This function has no return value. Syntax (halt) 13.7.5 Setting The Current Conflict Resolution StrategyThis function sets the current conflict resolution strategy. The default strategy is depth. Syntax (set strategy <strategy>)
13.7.6 Getting The Current Conflict Resolution StrategyThis function returns the current conflict resolution strategy (depth, breadth, simplicity, complexity, lex, mea, or random). Syntax (get strategy) 13.7.7 Listing the Module Names on the Focus StackThe command list focus stack list all module names on the focus stack. The first name listed is the current focus. Syntax (list focus stack) 13.7.8 Removing all Module Names from the Focus StackThe command clear focus stack removes all module names from the focus stack. Syntax (clear focus stack) 13.7.9 Setting the Salience Evaluation BehaviorThis function sets the salience evaluation behavior. By default, salience values are only evaluated when a rule is defined. Syntax (set salience evaluation <value>)
13.7.10 Getting the Salience Evaluation BehaviorThis function returns the current salience evaluation behavior (when defined, when activated, or every cycle). Syntax (get salience evaluation) 13.7.11 Refreshing the Salience Value of Rules on the AgendaThis function forces reevaluation of saliences of rules on the agenda regardless of the current salience evaluation setting. This function has no return value. Syntax (refresh agenda [<module-name>])
13.8 Defglobal CommandsThe following commands manipulate defglobals. 13.8.1 Displaying the Text of a DefglobalDisplays the text required to define a given global variable. Note that unlike other constructs such as deffacts and definstances, defglobal definitions have no name associated with the entire construct. The variable name passed to ppdefglobal should not include the question mark or the asterisks (e.g. x is the variable name for the global variable ?*x*). This function has no return value. Syntax (ppdefglobal <global-variable-name>) 13.8.2 Displaying the List of DefglobalsDisplays the names of all defglobals. This function has no return value. Syntax (list defglobals [<module-name>])
13.8.3 Deleting a DefglobalThis function deletes a previously defined defglobal. Syntax (undefglobal <defglobal-name>)
13.8.4 Displaying the Values of Global VariablesDisplays the names and current values of all defglobals. This function has no return value. Syntax (show defglobals [<module-name>])
13.8.5 Setting the Reset Behavior of Global VariablesThis function sets the reset global variables behavior. When this behavior is enabled (TRUE by default) global variables are reset to their original values when the reset command is performed. The return value for this function is the old value for the behavior. Syntax (set reset globals <boolean-expression>) 13.8.6 Getting the Reset Behavior of Global VariablesThis function returns the current value of the reset global variables behavior (TRUE or FALSE). Syntax (get reset globals) 13.9 Deffunction CommandsThe following commands manipulate deffunctions. 13.9.1 Displaying the Text of a DeffunctionDisplays the text of a given deffunction. This function has no return value. Syntax (ppdeffunction <deffunction-name>) 13.9.2 Displaying the List of DeffunctionsDisplays the names of all deffunctions stored in the CLIPS environment. This function has no return value. Syntax (list deffunctions) 13.9.3 Deleting a DeffunctionThis function deletes a previously defined deffunction. Syntax (undeffunction <deffunction-name>)
13.10 Generic Function CommandsThe following commands manipulate generic functions. 13.10.1 Displaying the Text of a Generic Function HeaderDisplays the text of a given generic function header. This function has no return value. Syntax (ppdefgeneric <generic-function-name>) 13.10.2 Displaying the Text of a Generic Function MethodDisplays the text of a given method. Syntax (ppdefmethod <generic-function-name> <index>)
13.10.3 Displaying the List of Generic FunctionsDisplays the names of all generic functions stored in the CLIPS environment. Syntax (list defgenerics [<module-name>])
13.10.4 Displaying the List of Methods for a Generic FunctionIf no name is given, this function lists all generic function methods in the CLIPS environment. If a name is given, then only the methods for the named generic function are listed. The methods are listed in decreasing order of precedence (see section 8.5.2) for each generic function. Method indices can be seen using this function. This function has no return value. Syntax (list defmethods [<generic-function-name>]) 13.10.5 Deleting a Generic FunctionThis function deletes a previously defined generic function. Syntax (undefgeneric <generic-function-name>)
13.10.6 Deleting a Generic Function MethodThis function deletes a previously defined generic function method. Syntax (undefmethod <generic-function-name> <index>)
13.10.7 Previewing a Generic Function CallThis debugging function lists all applicable methods for a particular generic function call in order of decreasing precedence (see section 8.5.2). The function list defmethods is different in that it lists all methods for a generic function. Syntax (preview generic <generic-function-name> <expression>*) This function does not actually execute any of the methods, but any side effects of evaluating the generic function arguments and any query parameter restrictions (see section 8.4.3) in methods do occur. The output for the first example in section 8.5.2 would be as follows:
CLIPS> (preview-generic + 4 5) + #7 (INTEGER <qry>) (INTEGER <qry>) + #8 (INTEGER <qry>) (NUMBER) + #3 (INTEGER) (INTEGER) + #4 (INTEGER) (NUMBER) + #6 (NUMBER) (INTEGER <qry>) + #2 (NUMBER) (INTEGER) + #SYS1 (NUMBER) (NUMBER) ($? NUMBER) + #5 (NUMBER) (NUMBER) ($? PRIMITIVE) CLIPS> 13.11 CLIPS Object Oriented Language (COOL) CommandsThe following commands manipulate elements of COOL. 13.11.1 Class CommandsThe following commands manipulate defclasses. 13.11.1.1 Displaying the Text of a DefclassDisplays the text of a given defclass. This function has no return value. Syntax (ppdefclass <class-name>) 13.11.1.2 Displaying the List of DefclassesDisplays the names of all defclasses stored in the CLIPS environment. If <module name> is unspecified, then the names of all defclasses in the current module are displayed. If <module name> is specified, then the names of all defclasses in the specified module are displayed. If <module name> is the symbol *, then the names of all defclasses in all modules are displayed. This function has no return value. Syntax (list defclasses [<module-name>]) 13.11.1.3 Deleting a DefclassThis function deletes a previously defined defclass and all its subclasses from the CLIPS environment. Syntax (undefclass <class-name>)
13.11.1.4 Examining a ClassThis function provides a verbose description of a class including: abstract role (whether direct instances can be created or not), direct superclasses and subclasses, class precedence list, slots with all their facets and sources, and all recognized message handlers. This function has no return value. Syntax (describe class <class-name>) Example CLIPS> (defclass CHILD (is-a USER) (role abstract) (multislot parents (cardinality 2 2)) (slot age (type INTEGER) (range 0 18)) (slot sex (access read-only) (type SYMBOL) (allowed-symbols male female) (storage shared))) CLIPS> (defclass BOY (is-a CHILD) (slot sex (source composite) (default male))) CLIPS> (defmessage-handler BOY play () (printout t “The boy is now playing…” crlf)) CLIPS> (describe-class CHILD) ==================================================================== ******************************************************************** Abstract: direct instances of this class cannot be created.
Inheritance Precedence: CHILD USER OBJECT Direct Subclasses: BOY -------------------------------------------------------------------- SLOTS : FLD DEF PRP ACC STO MCH SRC VIS CRT OVRD-MSG SOURCE(S) parents : MLT STC INH RW LCL RCT EXC PRV NIL put-parents CHILD age : SGL STC INH RW LCL RCT EXC PRV NIL put-age CHILD sex : SGL STC INH R SHR RCT EXC PRV NIL NIL CHILD
parents : + + + + + + + + RNG:[-oo..+oo] CRD:[2..2] age : + RNG:[0..18] sex : # ------------------------------------------------------------------- Recognized message-handlers: init primary in class USER delete primary in class USER create primary in class USER print primary in class USER direct-modify primary in class USER message-modify primary in class USER direct-duplicate primary in class USER message-duplicate primary in class USER ******************************************************************** ==================================================================== CLIPS>
13.11.1.5 Examining the Class HierarchyThis function provides a rudimentary display of the inheritance relationships between a class and all its subclasses. Indentation indicates a subclass. Because of multiple inheritance, some classes may appear more than once. Asterisks mark classes which are direct subclasses of more than one class. With no arguments, this function starts with the root class OBJECT. This function has no return value. Syntax (browse classes [<class-name>]) Example CLIPS> (defclass a (is-a USER)) CLIPS> (defclass b (is-a USER)) CLIPS> (defclass c (is-a a b)) CLIPS> (defclass d (is-a USER)) CLIPS> (defclass e (is-a c d)) CLIPS> (defclass f (is-a e)) CLIPS> (browse-classes) OBJECT PRIMITIVE NUMBER INTEGER FLOAT LEXEME SYMBOL STRING MULTIFIELD ADDRESS EXTERNAL-ADDRESS FACT-ADDRESS INSTANCE-ADDRESS * INSTANCE INSTANCE-ADDRESS * INSTANCE-NAME USER INITIAL-OBJECT a c * e * f b c * e * f d e * f CLIPS> 13.11.2 Message handler CommandsThe following commands manipulate defmessage handlers. 13.11.2.1 Displaying the Text of a Defmessage handlerDisplays the text of a given defmessage handler. This function has no return value. Syntax Defaults are outlined.
[<handler-type>]) <handler-type> ::= around | before | primary | after 13.11.2.2 Displaying the List of Defmessage handlersWith no arguments, this function lists all handlers in the system. With one argument, this function lists all handlers for the specified class. If the optional argument “inherit” is given, inherited message handlers are also included. This function has no return value. Syntax (list defmessage handlers [<class-name> [inherit]]) Example List all primary handlers in the system.
CLIPS> (defmessage-handler A foo ()) CLIPS> (list-defmessage-handlers A) foo primary in class A. For a total of 1 message-handler. CLIPS> (list-defmessage-handlers A inherit) init primary in class USER. delete primary in class USER. create primary in class USER. print primary in class USER. foo primary in class A. For a total of 4 message-handlers. CLIPS> 13.11.2.3 Deleting a Defmessage handlerThis function deletes a previously defined message handler. Syntax Defaults are outlined.
[<handler-type>]) <handler-type> ::= around | before | primary | after
Example Delete all primary handlers in the system.
CLIPS> 13.11.2.4 Previewing a MessageDisplays a list of all the applicable message handlers for a message sent to an instance of a particular class. The level of indentation indicates the number of times a handler is shadowed, and lines connect the beginning and ending portions of the execution of a handler if it encloses shadowed handlers. The right double angle brackets indicate the beginning of handler execution, and the left double angle brackets indicate the end of handler execution. Message arguments are not necessary for a preview since they do not dictate handler applicability. Syntax (preview send <class-name> <message-name>) Example For the example in section 9.5.3, the output would be:
| » my-message around in class OBJECT | | » my-message before in class USER | | « my-message before in class USER | | » my-message before in class OBJECT | | « my-message before in class OBJECT | | » my-message primary in class USER | | | » my-message primary in class OBJECT | | | « my-message primary in class OBJECT | | « my-message primary in class USER | | » my-message after in class OBJECT | | « my-message after in class OBJECT | | » my-message after in class USER | | « my-message after in class USER | « my-message around in class OBJECT « my-message around in class USER CLIPS> 13.11.3 Definstances CommandsThe following commands manipulate definstances. 13.11.3.1 Displaying the Text of a DefinstancesDisplays the text of a given definstances. This function has no return value. Syntax (ppdefinstances <definstances-name>) 13.11.3.2 Displaying the List of DefinstancesDisplays the names of all definstances stored in the CLIPS environment. This function has no return value. Syntax (list definstances) 13.11.3.3 Deleting a DefinstancesThis function deletes a previously defined definstances. Syntax (undefinstances <definstances-name>)
13.11.4 Instances CommandsThe following commands manipulate instances of user defined classes. 13.11.4.1 Listing the InstancesIf no arguments are specified, all instances in scope of the current module are listed. If a module name is given, all instances within the scope of that module are given. If “*” is specified (and there is no module named “*”), all instances in all modules are listed (only instances which actually belong to classes of a module are listed for each module to prevent duplicates). If a class name is specified, only the instances for the named class are listed. If a class is specified, then the optional keyword inherit causes this function to list instances of subclasses of the class as well. This function has no return value. Syntax (instances [<module-name> [<class-name> [inherit]]]) 13.11.4.2 Printing an Instance’s Slots from a HandlerThis function operates implicitly on the active instance (see section 9.4.1.1) for a message, and thus can only be called from within the body of a message handler. This function directly prints the slots of the active instance and is the one used to implement the print handler attached to class USER (see section 9.4.4.3). This function has no return value. Syntax (ppinstance) 13.11.4.3 Saving Instances to a Text FileThis function saves all instances in the CLIPS environment to the specified file in the following format:
<slot-override> ::= (<slot-name> <single-field-value>*)
Syntax (save instances <file-name> [local | visible [[inherit] <class>+])
13.11.4.4 Saving Instances to a Binary FileThe function bsave instances works exactly like save instancesexcept that the instances are saved in a binary format which can only be loaded with the function bload instances. The advantage to this format is that loading binary instances can be much faster than loading text instances for large numbers of instances. The disadvantage is that the file is not usually portable to other platforms. Syntax (save instances <file-name> [local | visible [[inherit] <class>+]) 13.11.4.5 Loading Instances from a Text FileThis function loads instances from a file into the CLIPS environment. It can read files created with save instances or any ASCII text file. Each instance should be in the format described in section 13.11.4.3 (although the instance name can be left unspecified). Calling load instances is exactly equivalent to a series of make instance calls (in CLIPS version 5.1, slot access restrictions, such as read only, were suspended during calls to load instances). This function returns the number of instances loaded or 1 if it could not access the instance file. Syntax (load instances <file-name>) 13.11.4.6 Loading Instances from a Text File without Message PassingThe function restore instances loads instances from a file into the CLIPS environment. It can read files created with save instances or any ASCII text file. Each instance should be in the format described in section 13.11.4.3 (although the instance name can be left unspecified). It is similar in operation to load instances, however, unlike load instances, restore instances does not use message passing for deletions, initialization, or slot overrides. Thus in order to preserve object encapsulation, it is recommended that restore instances only be used with files generated by save instances. This function returns the number of instances loaded or 1 if it could not access the instance file. Syntax (restore instances <file-name>) 13.11.4.7 Loading Instances from a Binary FileThis function is similar to restore instances except that it can only work with files generated by bsave instances. See section 13.11.4.4 for a discussion of the merits of using binary instance files. Syntax (bload instances <file-name>) 13.12 Defmodule CommandsThe following commands manipulate defmodule constructs. 13.12.1 Displaying the Text of a DefmoduleDisplays the text of a given defmodule. This function has no return value. Syntax (ppdefmodule <defmodule-name>) 13.12.2 Displaying the List of DefmodulesDisplays the names of all defmodule constructs stored in the CLIPS environment. This function has no return value. Syntax (list defmodules) 13.13 Memory Management CommandsThe following commands display CLIPS memory status information. CLIPS memory management is described more fully in the Advanced Programming Guide. 13.13.1 Determining the Amount of Memory Used by CLIPSReturns an integer representing the number of bytes CLIPS has currently in use or has held for later use. This number does not include operating system overhead for allocating memory. Syntax (mem used) 13.13.2 Determining the Number of Memory Requests Made by CLIPSReturns an integer representing the number of times CLIPS has requested memory from the operating system. If the operating system overhead for allocating memory is known, then the total memory used can be calculated by
Syntax (mem requests) 13.13.3 Releasing Memory Used by CLIPSReleases all free memory held internally by CLIPS back to the operating system. CLIPS will automatically call this function if it is running low on memory to allow the operating system to coalesce smaller memory blocks into larger ones. This function generally should not be called unless the user knows exactly what he/she is doing (since calling this function can prevent CLIPS from reusing memory efficiently and thus slow down performance). This function returns an integer representing the amount of memory freed to the operating system. Syntax (release mem) 13.13.4 Conserving MemoryTurns on or off the storage of information used for save and pretty print commands. This can save considerable memory in a large system. It should be called prior to loading any constructs. This function has no return value. Syntax (conserve mem <value>)
13.14 On Line Help SystemCLIPS provides an on line help facility for use from the top level interface. The help system uses CLIPS’ external text manipulation capabilities (see section 13.15). Thus, it is possible to add or change entries in the help file or to construct new help files with information specific to the user’s system. 13.14.1 Using the CLIPS Help FacilityThe help facility displays menus of topics and prompts the user for a choice. It then references the help file for that information. The help facility can be called with or without a command line topic. Syntax (help [<path>])
? When specified at the end of a path, this forces a display of the current menu, even on branch ups. <nil> Giving no topic field will branch up one level.
13.14.2 Finding the Help FileThe help facility reads help information from a file during execution. Users may wish to change the location of the help file to meet the configuration of their system. The help path function was provided to allow this. Syntax (help path [<help-file-name>])
13.15 External Text ManipulationCLIPS provides a set of functions to build and access a hierarchical lookup system for multiple external files. Each file contains a set of text entries in a special format that CLIPS can later reference and display. The basic concept is that CLIPS retains a “map” of the text file in memory and can easily pull sections of text from the file without having to store the whole file in memory and without having to sequentially search the file for the appropriate text. 13.15.1 External Text File FormatEach external text file to be loaded into CLIPS must be described in a particular way. Each topic entry in each file must be in the format shown following. Syntax <level-num> <entry-type> BEGIN-ENTRY- <topic-name> • • Topic information in form to be displayed when referenced. • • END-ENTRY
Example
0MBEGIN-ENTRY-ROOT
Example
0MBEGIN-ENTRY-ROOT1
| / \
SUBTOPIC3 SUBTOPIC1 SUBTOPIC2 13.15.2 External Text Manipulation FunctionsThe following functions are used by the help facility (see section 13.14) and can be used by users to maintain their own information system. 13.15.2.1 FetchThe function fetch loads the named file (which must be in the format defined in section 13.15.1) into the internal lookup table. Syntax (fetch <file-name>)
13.15.2.2 Print regionThe function print region looks up a specified entry in a particular file which has been loaded previously into the lookup table and prints the contents of that entry to the specified output. Syntax (print region <logical-name> <file-name> <topic-field>*)
? When specified at the end of a path, this forces a display of the current menu, even on branch ups. <nil> Giving no topic field will branch up one level.
Examples To display the entry for ROOT SUBTOPIC from the file foo.lis on the screen, type
7 CLIPS> (print-region t “foo.lis” roo sub)
TRUE CLIPS> (print-region t “foo.lis” ”?“)
TRUE CLIPS> (print-region t “foo.lis” ^ root1 sub)
TRUE CLIPS> (print-region t “foo.lis” sub)
TRUE CLIPS> (print-region t “foo.lis” ^ subtopic2)
TRUE CLIPS> (print-region t “foo.lis” ^ root2)
TRUE CLIPS> (toss “foo.lis”) TRUE CLIPS> 13.15.2.3 TossThe function toss unloads the named file from the internal lookup table and releases the memory back to the system. Syntax (toss <file-name>)
13.16 Profiling CommandsThe following commands provide the ability to profile CLIPS programs for performance. 13.16.1 Setting the Profiling Report ThresholdThe set-profile-percent-threshold command sets the minimum percentage of time that must be spent executing a construct or user function for it to be displayed by the profile-info command. By default, the percent threshold is zero, so all constructs or user-functions that were profiled and executed at least once will be displayed by the profile-info command. The return value of this function is the old percent threshold. Syntax (set-profile-percent-threshold <number in the range 0 to 100>) 13.16.2 Getting the Profiling Report ThresholdThe get-profile-percent-threshold command returns the current value of the profile percent threshold. Syntax (get-profile-percent-threshold) 13.16.3 Resetting Profiling InformationThe profile-reset command resets all profiling information currently collected for constructs and user functions. Syntax (profile-reset) 13.16.4 Displaying Profiling InformationThe profile-info command displays profiling information currently collected for constructs or user functions. Profiling information is displayed in six columns. The first column contains the name of the construct or user function profiled. The second column indicates the number of times the construct or user function was executed. The third column is the amount of time spent executing the construct or user function. The fourth column is the percentage of time spent in the construct or user function with respect to the total amount of time profiling was enabled. The fifth column is the total amount of time spent in the first execution of the construct or user function and all subsequent calls to other constructs/user functions. The sixth column is the percentage of this time with respect to the total amount of time profiling was enabled. Syntax (profile-info) 13.16.5 Profiling Constructs and User FunctionsThe profile command is used to enable/disable profiling of constructs and user functions. If constructs are profiled, then the amount of time spent executing deffunctions, generic functions, message handlers, and the RHS of defrules is tracked. If user-functions are profiled, then the time spent executing system and user defined functions is tracked. System defined functions include predefined functions available for your own use such as the < and numberp functions in addition to low level internal functions which are not available for your use (these will usually appear in profile-info output in all capital letters or surrounded by parentheses). It is not possible to profile constructs and user-functions at the same time. Enabling one disables the other. The off keyword argument disables profiling. Profiling can be repeatedly enable and disabled as long as only one of constructs or user-functions is consistently enabled. The total amount of time spent with profiling enabled will be displayed by the profile-info command. If profiling is enabled from the command prompt, it is a good idea to place the calls enabling and disabling profiling within a single progn function call. This will prevent the elapsed profiling time from including the amount of time needed to type the commands being profiled. Syntax (profile constructs | user-functions | off) Example CLIPS> (clear) CLIPS> (deffacts start (fact 1)) CLIPS> (deffunction function-1 (?x) (bind ?y 1) (loop-for-count (* ?x 10) (bind ?y (+ ?y ?x)))) CLIPS> (defrule rule-1 ?f ← (fact ?x&:(< ?x 100)) ⇒ (function-1 ?x) (retract ?f) (assert (fact (+ ?x 1)))) CLIPS> (reset) CLIPS> (progn (profile constructs) (run) (profile off)) CLIPS> (profile-info) Profile elapsed time = 0.474921 seconds
-------------- ——- —— —– ——— ——
CLIPS> (profile-reset) CLIPS> (reset) CLIPS> (progn (profile user-functions) (run) (profile off)) CLIPS> (profile-info) Profile elapsed time = 12.0454 seconds
------------- ——- —— —– ——— —— retract 99 0.007953 0.07% 0.010646 0.09% assert 99 0.012160 0.10% 0.032766 0.27% run 1 0.047421 0.39% 12.045301 100.00% profile 1 0.000049 0.00% 0.000049 0.00% * 99 0.005579 0.05% 0.007610 0.06% + 49599 3.626217 30.10% 5.765490 47.86% < 99 0.005234 0.04% 0.007749 0.06% progn 49698 2.353003 19.53% 11.997880 99.61% loop-for-count 99 1.481078 12.30% 11.910553 98.88% PCALL 99 0.020747 0.17% 11.943234 99.15% FACT_PN_VAR3 99 0.002515 0.02% 0.002515 0.02% FACT_JN_VAR1 99 0.002693 0.02% 0.002693 0.02% FACT_JN_VAR3 198 0.004718 0.04% 0.004718 0.04% FACT_STORE_MULTIFIELD 99 0.005478 0.05% 0.012857 0.11% PROC_PARAM 49599 1.036460 8.60% 1.036460 8.60% PROC_GET_BIND 49500 1.102682 9.15% 1.102682 9.15% PROC_BIND 49599 2.331363 19.35% 8.089474 67.16% CLIPS> (set-profile-percent-threshold 1) 0.0 CLIPS> (profile-info) Profile elapsed time = 12.0454 seconds
------------- ——- —— —– ——— —— + 49599 3.626217 30.10% 5.765490 47.86% progn 49698 2.353003 19.53% 11.997880 99.61% loop-for-count 99 1.481078 12.30% 11.910553 98.88% PROC_PARAM 49599 1.036460 8.60% 1.036460 8.60% PROC_GET_BIND 49500 1.102682 9.15% 1.102682 9.15% PROC_BIND 49599 2.331363 19.35% 8.089474 67.16% CLIPS> (profile-reset) CLIPS> (profile-info) CLIPS>
Appendix A Support InformationA.1 Questions and InformationInquiries related to the use or installation of CLIPS can be sent via electronic mail to clips@ghg.net.
A.2 CLIPS List ServerAn electronic conferencing facility, sponsored by Distributed Computing Systems (http://www.discomsys.com), is also available to CLIPS users. Subscribers to this facility may send questions, observations, answers, editorials, etc., in the form of electronic mail to the conference. All subscribers will have a copy of these messages reflected back to them at their respective electronic mail addresses. To subscribe, send a single line message to clips request@discomsys.com containing the word “subscribe”. The subject field is ignored but the address found in the ‘Reply:’, ‘Reply to:’, or ‘From:’ field will be entered in the distribution list. Upon subscription you will receive a mail message instructing you how to participate in the conference from that point forward. Save this mail message. You may need the instructions later if you wish to unsubscribe from the list server.
If you wish to remove yourself from the conference and discontinue receiving mail simply send a message to clips-request@discomsys.com with “unsubscribe” as the message text. If you want to unsubscribe using another email account than the one you subscribed with, then append the original subscribing email account to the text of the message. For example: “unsubscribe john.doe@account.net”. Do not send unsubscribe messages to clips@discomsys.com! This sends a mail message to every member of the list. If you need to get in contact with the list administrator (for trouble unsubscribing or other questions about the list), send email to clips-owner @discomsys.com.
A.3 CLIPS Developers’ ForumThe CLIPS Developers’ Forum, a thread-based message board, is available at http://www.cpbinc.com/clips. This board exists to provide a site for discussion of research, development, and implementation of the CLIPS expert systems and related technologies. The hosting services for this web page are provided by CPB, Inc. A.4 DocumentationThe CLIPS Reference Manuals and User's Guide are available in Portable Document Format (PDF) at the URL http://www.ghg.net/clips/download/documentation/. Adobe Acrobat Reader, which can be downloaded at http://www.adobe.com/prodindex/acrobat/readstep.html, is needed to view PDF files.
International Thompson Publishing 7625 Empire Dr. Florence, KY 41042 Phone: (800) 354-9706 Phone: (606) 525-2230
20 Park Plaza Boston, MA 02116-4324 Phone: (617) 542-3377 Fax: (617) 338-6134 A.5 CLIPS Source Code and ExecutablesCLIPS executables can be downloaded from http://www.ghg.net/clips/download/executables/. The source code can be downloaded from http://www.ghg.net/clips/download/source/.
Appendix B Update Release NotesThe following sections denote the changes and bug fixes for CLIPS versions 6.01, 6.02, 6.03, and 6.04, 6.05, 6.1, and 6.2. B.1 Version 6.2• Environments – It is now possible in an embedded application to create multiple environments into which programs can be loaded. See section 9 of The Advanced Programming Guide for more details
B.2 Version 6.1• C++ Compatible – The CLIPS source code can now be compiled using either an ANSI C or C++ compiler. Minimally, non-ANSI C compilers must support full ANSI style function prototypes and the void data type in order to compile CLIPS.
sort (see section 12.7.9)
open (see section 12.4.2.1). Files can be opened with binary write access. B.3 Version 6.05• Bug Fixes The following bugs were fixed by the 6.05 release:
numbers.
replace-member$ (see section 12.2.15) slot-default-value (see section 12.16.1.24) B.4 Version 6.04• New Functions and Commands Several new functions and commands have been added. They are:
fact-existp (see section 12.9.7) fact-relation (see section 12.9.8) fact-slot-names (see section 12.9.10) fact-slot-value (see section 12.9.9) get-fact-list (see section 12.9.11) load* (see section 13.1.2)
B.5 Version 6.03• Bug Fixes The following bugs were fixed by the 6.03 release:
• Memory allocation problems existed on machines with architectures utilizing pointers and integers larger than 32-bits. • When two object patterns containing more than one multifield reference shared at least one of those references, CLIPS could crash. • The explicit getenv definition in edterm.c conflicted with the ANSI C stdlib.h definition. • More than 32,768 references to a single symbol on machines with two byte integers would create internal errors. • Errors generated when calling the Send C function from an embedded application would prevent subsequent calls from working correctly. • Typing an ‘&’ in the Windows 3.1 CLIPS interface dialog window caused a ‘_’ to appear instead. • Fact patterns in which a single slot contained more than one multifield variable didn’t always work properly. • The isalpha library function did not return the correct value in the scanner.c module when ctype.h is included after stdio.h when creating a Win32 executable with Borland C++ v4.0. • Errors in the argument string passed to CLIPSFunctionCall would cause subsequent calls to CLIPSFunctionCall to fail. • Memory deallocation could work improperly if BLOCK_MEMORY was used and a memory block larger than the block memory table is deallocated. • The set-strategy function returned the new value of the conflict resolution strategy rather than the old value. • Redefining a deftemplate could cause a crash under some conditions. • Selecting 32 character construct names in the construct browsers of the Windows 3.1 CLIPS interface would cause a crash. • Constraint violations occurred for semantically correct rules containing multifield variables and expressions which referred to those variables. • Messages could be sent to out of scope instances. • The CLIPS System Error message was printed instead of an invalid slot name error message when invalid slot names were used. B.6 Version 6.02• Bug Fixes The following bugs were fixed by the 6.02 release:
• The code generated by the constructs-to-c command for rules with logical or or conditional elements would not compile. • Loading a binary file with defglobals in it would cause a crash if defglobals were being watched.
• An inapplicable object pattern could be matched against an object if a great deal of object pattern-matching occurred over a long period of time. • The function slot-types could corrupt memory when called for any slot that could hold an instance name. • Instance-set query function iteration variables returned just base instance names. Thus, if one of the instances is from an imported class, other operations on that variable may not be able to access the instance. • Read-only slots with a static default value were not automatically shared. • The slot-cardinality function caused a crash when called for single-field slots. • Link errors occured in insmngr.c when the DEFRULE_CONSTRUCT flag was disabled, but the LOGICAL_DEPENDENCIES flag was enabled in setup.h • Calls to the return function within a progn$ function call did not work properly. • Changing the focus on the RHS of a rule and then issuing a return command would remove the newly focused module and not the rule’s module from the focus stack. • The cmptblty.h header file was not included in some of the distribution packages.
• The instance-set query functions generated an invalid slot reference when the ‘:’ is the last character in a instance-set member variable name longer than two characters. B.7 Version 6.01• Bug Fixes The following bugs were fixed by the 6.01 release:
Appendix C GlossaryThis section defines some of the terminology used throughout this manual.
Appendix D Integrated EditorCLIPS includes a fully integrated version of the full screen MicroEMACS editor. You may call the editor from CLIPS, compile full buffers or just sections of the editor (incremental compile), temporarily exit the editor back to CLIPS, or permanently exit the editor. Since the editor is full screen, portions of it are highly machine dependent. As it is currently set up, the editor will run on VAX VMS machines using VT100 or VT240 compatible terminals, UNIX systems which support TERMCAP, the IBM PC, and most IBM compatibles.
D.1 Special characters
D.2 Control Commands
D.3 Extended (Control X) Commands
D.4 Meta Commands (Activated by <esc> or <ctrl [>)
Appendix E Performance ConsiderationsThis appendix explains various techniques that the user can apply to a CLIPS program to maximize performance. Included are discussions of pattern ordering in rules, use of deffunctions in lieu of non overloaded generic functions, parameter restriction ordering in generic function methods, and various approaches to improving the speed of message passing and reading slots of instances. E.1 Ordering of Patterns on the LHSThe issues which affect performance of a rule based system are considerably different from those which affect conventional programs. This section discusses the single most important issue: the ordering of patterns on the LHS of a rule.
E.2 Deffunctions versus Generic FunctionsDeffunctions execute more quickly than generic function because generic functions must first examine their arguments to determine which methods are applicable. If a generic function has only one method, a deffunction probably would be better. Care should be taken when determining if a particular function truly needs to be overloaded. In addition, if recompiling and relinking CLIPS is not prohibitive, user defined external functions are even more efficient than deffunctions. This is because deffunction are interpreted whereas external functions are directly executed. For more details, see sections 7 and 8.2. E.3 Ordering of Method Parameter RestrictionsWhen the generic dispatch examines a generic function’s method to determine if it is applicable to a particular set of arguments, it examines that method’s parameter restrictions from left to right. The programmer can take advantage of this by placing parameter restrictions which are less frequently satisfied than others first in the list. Thus, the generic dispatch can conclude as quickly as possible when a method is not applicable to a generic function call. If a group of restrictions are all equally likely to be satisfied, placing the simpler restrictions first, such as those without queries, will also allow the generic dispatch to conclude more quickly for a method that is not applicable. For more details, see section 8.4.3. E.4 Instance Addresses versus Instance NamesCOOL allows instances of user defined classes to be referenced either by address or by name in functions which manipulate instances, such as message passing with the send function. However, when an instance is referenced by name, CLIPS must perform an internal lookup to find the instance address anyway. If the same instance is going to be manipulated many times, it might be advantageous to store the instance address and use that as a reference. This will allow CLIPS to always go directly to the instance. For more details, see sections 2.4.2 and 12.16.4.6. E.5 Reading Instance Slots DirectlyNormally, message passing must be used to read or set a slot of an instance. However, slots can be read directly within instance set queries and message handlers, and they can be set directly within message handlers. Accessing slots directly is significantly faster than message passing. Unless message passing is required (because of slot daemons), direct access should be used when allowed. For more details, see sections 9.4.2, 9.4.3, 9.4.4, 9.6.3, 9.6.4 and 9.7.3.
Appendix F CLIPS Warning MessagesCLIPS typically will display two kinds of warning messages: those associated with executing constructs and those associated with loading constructs. This appendix describes some of the more common warning messages and what they mean. Each message begins with a unique identifier enclosed in brackets followed by the keyword WARNING; the messages are listed here in alphabetic order according to the identifier.
This may cause files to be overwritten if file name length is limited on your platform. The constructs to c command generates file names using the file name prefix supplied as an argument. If this base file name is longer than three characters, then the possibility exists that files may be overwritten if file name length is limited on your platform.
The constructs to c command generates arrays for storing data structures. If the SHORT_LINK_NAMES compiler flag is enabled, then this warning message is displayed if generated array names exceed six characters in length.
or [CSTRNCMP1] WARNING: Constraints are not saved with a constructs to c image when dynamic constraint checking is disabled These warnings occur when dynamic constraint checking is disabled and the constructs to c or bsave commands are executed. Constraints attached to deftemplate and defclass slots will not be saved with the runtime or binary image in these cases since it is assumed that dynamic constraint checking is not required. Enable dynamic constraint checking with the set dynamic constraint checking function before calling constructs to c or bsave in order to include constraints in the runtime or binary image.
During a clear or deletion of all deffunctions, only the actions of a deffunction were deleted because another construct which also could not be deleted referenced the deffunction.
CLIPS> (deffunction foo () (printout t “Hi there!” crlf)) CLIPS> (deffunction bar () (foo) (undeffunction *)) CLIPS> (bar)
This warning occurs when a generic function method restricted by defclasses is loaded using the bload command into a CLIPS configuration where the object language is not enabled. The restriction containing the defclass will match any of the primitive types.
This warning occurs when an around message handler is loaded using the bload command into a CLIPS configuration not supporting imperative message handlers.
This warning occurs when a before or an after message handler is loaded using the bload command into a CLIPS configuration not supporting auxiliary message handlers.
Appendix G CLIPS Error MessagesCLIPS typically will display two kinds of error messages: those associated with executing constructs and those associated with loading constructs. This appendix describes some of the more common error messages and what they mean. Each message begins with a unique identifier enclosed in brackets; the messages are listed here in alphabetic order according to the identifier.
Salience requires a integer argument and will otherwise result in this error message.
CLIPS> (defrule error (declare (salience a)) ⇒)
The range of allowed salience has an explicit limit; this error message will result if the value is out of that range.
CLIPS> (defrule error (declare (salience 20000)) ⇒)
When an error results from evaluating a salience value for a rule, this error message is given.
This message occurs when two facts or instances are bound to the same pattern address variable.
CLIPS> (defrule error ?f ← (a) ?f ← (b) ⇒)
A variable first bound within a pattern cannot be later bound to a fact address.
CLIPS> (defrule error (a ?f) ?f ← (b) ⇒)
Variables on the LHS of a rule cannot be bound to both single and multifield variables.
CLIPS> (defrule error (a ?x $?x) ⇒) [ANALYSIS4] Variable <variable name> [found in the expression <expression>] was referenced in CE <CE number> <field or slot identifier> before being defined A variable cannot be referenced before it is defined and, thus, results in this error message.
CLIPS> (defrule foo (a ~?x) ⇒)
This error occurs when a function receives less than the minimum number or more than the maximum number of argument(s) expected.
This error occurs when the specified function cannot open a file.
This error occurs when a function is passed fewer arguments than were expected.
This error occurs when a function that expects a precise number of argument(s) receives an incorrect number of arguments.
This error occurs when a function does not receive the minimum number of argument(s) that it expected.
This error occurs when a function receives more than the maximum number of argument(s) expected.
This error occurs when a function is passed the wrong type of argument.
This error occurs when a function requests from another function the wrong type of argument, typically a string or symbol, when expecting a number or vice versa.
If the bload command was used to load in a binary image, then the named construct cannot be entered until a clear command has been performed to remove the binary image.
This error occurs when the bload command is used to load a file that was not created with the bsave command.
This error occurs when the bload command is used to load a file that was created with the bsave command using a different version of CLIPS.
Binary load cannot continue. A binary load cannot be performed unless the current CLIPS environment can be cleared.
Binary <operation> cannot continue. This error occurs when the current binary image cannot be cleared because some constructs are still being used. The <operation> in progress may either be a binary load or a binary clear.
This error occurs when a binary image is loaded that calls functions which were available in the CLIPS executable that originally created the binary image, but which are not available in the CLIPS executable that is loading the binary image.
The bsave command does not work when a binary image is loaded.
This error message occurs when the function slot publicp is given an inherited slot. This function can only be used on slots defined in the given class.
CLIPS> (defclass FOO (is-a USER) (slot woz (visibility private))) CLIPS> (defclass BAR (is-a FOO)) CLIPS> (slot-publicp BAR woz)
This error message occurs when a function is given a non existent class name.
CLIPS> (class-slots FOO)
This error is usually caused by too many simultaneously active instance set queries, e.g., do for all instances. The direct or indirect nesting of instance set query functions is limited in the following way:
CLIPS> (deffunction my-func () (do-for-instance ((?a USER) (?b USER) (?c USER)) TRUE (printout t ?a “ ” ?b “ ” ?c crlf)) ; The sum here is C1 = 3 which is OK. CLIPS> (do-for-all-instances ((?a OBJECT) (?b OBJECT)) TRUE (my-func))
Only concrete classes can be reactive.
CLIPS> (defclass FOO (is-a USER) (role abstract) (pattern-match reactive))
Predefined system classes cannot be modified by the user.
CLIPS> (defclass STRING (is-a NUMBER))
This error occurs when an attempt to redefine a class is made under one or both of the following two circumstances:
2) The class (or any of its subclasses) appear in the parameter restrictions of any generic function method.
CLIPS> (defclass A (is-a USER)) CLIPS> (defmethod foo ((?a A LEXEME))) CLIPS> (defclass A (is-a OBJECT)))
Only one specification of a class attribute is allowed.
CLIPS> (defclass A (is-a USER) (role abstract) (role concrete))
Slots in a defclass must be unique.
CLIPS> (defclass A (is-a USER) (slot foo) (slot foo))
Only one occurrence of a facet per slot is allowed.
CLIPS> (defclass A (is-a USER) (slot foo (access read-only) (access read-write)))
Single field slots by definition have a cardinality of one.
CLIPS> (defclass A (is-a USER) (slot foo (cardinality 3 5)))
Since slots cannot be unbound and read only slots cannot be set after initial creation of the instance, read only slots must have a default value.
CLIPS> (defclass A (is-a USER) (slot foo (access read-only) (default ?NONE)))
Since read only slots cannot be changed after initializationof the instance, a write accessor (put message handler) is not allowed.
CLIPS> (defclass A (is-a USER) (slot foo (access read-only) (create-accessor write)))
no inherit slots are by definition not accessible to subclasses and thus only visible to the parent class.
CLIPS> (defclass A (is-a USER) (slot foo (propagation no-inherit) (visibility public)))
This message occurs when a top level command does not begin with a '(', constant, or global variable.
CLIPS> ) [COMMLINE2] Expected a command. This message occurs when a top level command is not a symbol.
CLIPS> (“facts”
A '.' cannot be used in the file name prefix that is passed to the constructs to c command since this prefix is used to generate file names and some operating systems do not allow more than one '.' to appear in a file name.
This error occurs when the clear command is issued when a construct is in use (such as a rule that is firing).
This error occurs when the load command expects a left parenthesis followed a construct type and these token types are not found.
This error occurs when the name is missing for a construct that requires a name.
CLIPS> (defgeneric ())
or [CSTRCPSR3] Cannot define defmodule <defmodule name> because of an import/export conflict cause by the <construct type> <construct name>. A construct cannot be defined if defining the construct would allow two different definitions of the same construct type and name to both be visible to any module.
CLIPS> (defmodule MAIN (export ?ALL)) CLIPS> (deftemplate MAIN::foo) CLIPS> (defmodule BAR (import MAIN ?ALL)) CLIPS> (deftemplate BAR::foo (slot x))
A construct cannot be redefined while it is being used by another construct or other data structure (such as a fact or instance).
CLIPS> (clear) CLIPS> (deftemplate bar) CLIPS> (assert (bar)) <Fact-0> CLIPS> (deftemplate (bar (slot x)))
This error ID covers a range of messages indicating a type, value, range, or cardinality violation.
CLIPS> (deftemplate foo (slot x (type SYMBOL))) CLIPS> (assert (foo (x 3)))
This error message occurs when two slot attributes conflict.
CLIPS> (deftemplate foo (slot x (type SYMBOL) (range 0 2)))
or equal to the maximum <attribute> value. The minimum attribute value for the range and cardinality attributes must be less than or equal to the maximum attribute value for the attribute.
CLIPS> (deftemplate foo (slot x (range 8 1)))
The use of some slot attributes excludes the use of other slot attributes.
CLIPS> (deftemplate foo (slot x (allowed-values a) (allowed-symbols b)))
The arguments to an attribute must match the type expected for that attribute (e.g. integers must be used for the allowed integers attribute).
CLIPS> (deftemplate example (slot x (allowed-integers 3.0)))
The cardinality attribute can only be used for slots defined with the multislot keyword.
CLIPS> (deftemplate foo (slot x (cardinality 1 1)))
This error occurs when the default or default dynamic attribute for a single field slot does not contain a single value or an expression returning a single value.
CLIPS> (deftemplate error (slot x (default)))
A deffunction cannot have the same name as any construct.
CLIPS> (deffunction defgeneric ())
A deffunction cannot have the same name as any system or user defined external function.
CLIPS> (deffunction + ())
A deffunction cannot have the same name as any generic function.
CLIPS> (defgeneric foo) CLIPS> (deffunction foo ())
A deffunction can be loaded at any time except when a deffunction of the same name is already executing.
CLIPS> (deffunction foo () (build “(deffunction foo ())”)) CLIPS> (foo)
A deffunction cannot have the same name as any generic function imported from another module.
CLIPS> (defmodule MAIN (export ?ALL)) CLIPS> (defmethod foo ()) CLIPS> (defmodule FOO (import MAIN ?ALL)) CLIPS> (deffunction foo)
Problem resides in join #<pattern number> in rule(s): <problem rules>+ This error pinpoints other evaluation errors associated with evaluating an expression within the join network. The specific pattern of the problem rules is identified.
This error occurs when an argument passed to a math function is not in the domain of values for which a return value exists.
This error occurs when an argument to an extended math function would cause a numeric overflow.
This error occurs when an argument to a trigonometric math function would cause a singularity.
This error occurs when a local variable not set by a previous call to bind is accessed at the top level.
CLIPS> (progn ?error)
IThis error occurs only when an invalid function name is passed to the external C access routine CLIPSFunctionCall.
In the following example, '~' is recognized by CLIPS as an operator, not a function:
CLIPS> (+ (~ 3 4) 4)
In the following example, '~' is an operator and is illegal as an argument to a function call:
CLIPS> (⇐ ~ 4)
CLIPS does not recognize <name> as a declared function and gives this error message.
CLIPS> (xyz)
The sequence expansion operator cannot be used with certain functions.
CLIPS> (set-sequence-operator-recognition TRUE) FALSE CLIPS> (defrule foo (x $?y) ⇒ (assert (x1 $?y)))
Currently active fact: <newly assert fact> Problem resides in slot <slot name> Of pattern #<pattern number> in rule(s): <problem rules>+ This error pinpoints other evaluation errors associated with evaluating an expression within the pattern network. The specific pattern and field of the problem rules are identified.
or [FACTMNGR2] Facts may not be retracted during pattern matching Functions used on the LHS of a rule should not have side effects (such as the creation of a new instance or fact).
CLIPS> (defrule error (test (assert (blah))) ⇒) CLIPS> (reset)
This error occurs when an assert is attempted for a deftemplate which does not exist in a runtime or active bload image. In other situations, CLIPS will create an implied deftemplate if one does not already exist.
CLIPS> (clear) CLIPS> (bsave error.bin) TRUE CLIPS> (bload error.bin) TRUE CLIPS> (assert (error))
This error occurs when the generic function name passed to the undefmethod function does not exist.
CLIPS> (clear) CLIPS> (undefmethod yak 3)
This error occurs when an invalid method index is passed to undefmethod (e.g. a negative integer or a symbol other than *).
CLIPS> (defmethod foo ()) CLIPS> (undefmethod foo a))
It is illegal to specify a non wildcard method index when a wildcard is given for the generic function in the function undefmethod.
CLIPS> (undefmethod * 1)
A method corresponding to a system defined function cannot be deleted.
CLIPS> (defmethod integer ((?x SYMBOL)) 0) CLIPS> (list-defmethods integer) integer #SYS1 (NUMBER) integer #2 (SYMBOL) For a total of 2 methods. CLIPS> (undefmethod integer 1)
The generic function call arguments do not satisfy any method’s parameter restrictions.
CLIPS> (defmethod foo ()) CLIPS> (foo 1 2)
No shadowed method is available when the function call next method is called.
CLIPS> (call-next-method)
The class or type of a generic function argument could not be determined for comparison to a method type restriction.
CLIPS> (defmethod foo ((?a INTEGER))) CLIPS> (foo [bogus-instance])
This error occurs when call specific method is called with an inappropriate set of arguments for the specified method.
CLIPS> (defmethod foo ()) CLIPS> (call-specific-method foo 1 abc)
Defgenerics can’t be redefined while one of their methods is currently executing.
CLIPS> (defgeneric foo) CLIPS> (defmethod foo () (build “(defgeneric foo)”)) CLIPS> (foo) [GENRCFUN2] Unable to find method <name> #<index> in function <name>. No generic function method of the specified index could be found by the named function.
CLIPS> (defmethod foo 1 ()) CLIPS> (ppdefmethod foo 2)
No generic function method of the specified index could be found by the named function.
CLIPS> (preview-generic balh)
A right parenthesis completes the definition of a generic function header.
CLIPS> (defgeneric foo ())
An explicit index has been specified for a new method that does not match that of an older method which has identical parameter restrictions.
CLIPS> (defmethod foo 1 ((?a INTEGER))) CLIPS> (defmethod foo 2 ((?a INTEGER)))
A generic function cannot have the same name as any construct.
A deffunction cannot have the same name as any generic function imported from another module.
CLIPS> (defmodule MAIN (export ?ALL)) CLIPS> (deffunction foo ()) CLIPS> (defmodule FOO (import MAIN ?ALL)) CLIPS> (defmethod foo)
A generic function cannot have the same name as any deffunction.
A method index cannot be greater than the maximum value of an integer or less than 1.
CLIPS> (defmethod foo 0 ()) [GENRCPSR7] Expected a '(' to begin method parameter restrictions. A left parenthesis must begin a parameter restriction list for a method.
CLIPS> (defmethod foo)
A method parameter with restrictions must be a variable.
CLIPS> (defmethod foo ((abc)))
A method parameter must be a variable with or without restrictions.
CLIPS> (defmethod foo (abc))
A query parameter restriction must follow a type parameter restriction (if any).
CLIPS> (defmethod foo ((?a (< ?a 1) INTEGER)))
A method type parameter restriction may have only a single occurrence of a particular class.
CLIPS> (defmethod foo ((?a INTEGER INTEGER)))
Binding new variables in a method query parameter restriction is illegal.
CLIPS> (defmethod foo ((?a (bind ?b 1))))
Method parameter restrictions consist of zero or more class names and an optional query expression.
CLIPS> (defmethod foo ((?a 34)))
Classes in method type parameter restrictions must already be defined.
CLIPS> (defmethod foo ((?a bogus-class)))
All classes in a method type parameter restriction should be unrelated.
CLIPS> (defmethod foo ((?a INTEGER NUMBER)))
Some system functions canot be overloaded.
CLIPS> (defmethod if ())
A system function can not be overloaded with a method that has the exact number and types of arguments.
CLIPS> (defmethod integer ((?x NUMBER)) (* 2 ?x))
A global variable must be defined before it can be accessed at the command prompt or elsewhere.
CLIPS> (clear) CLIPS> ?*x*
A global variable must be defined before it can be accessed at the command prompt or elsewhere.
CLIPS> (clear) CLIPS> ?*x*
The incremental reset behaviour can only be changed when there are no currently defined rules.
A class may not inherit from itself.
CLIPS> (defclass A (is-a A))
All direct superclasses of a class must be unique.
CLIPS> (defclass A (is-a USER USER)) [INHERPSR3] A class must be defined after all its superclasses. Subclasses must be defined last.
CLIPS> (defclass B (is-a A))
All user defined classes must have at least one direct superclass.
CLIPS> (defclass A (is-a))
Precedence loop in superclasses: <class1> <class2> … <classn> <class1> No class precedence list satisfies the rules specified in section 9.3.1.1 for the given direct superclass list. The message shows a conflict for <class1> because the precedence implies that <class1> must both precede and succeed <class2> through <classn>. The full loop can be used to help identify which particular classes are causing the problem. This loop is not necessarily the only loop in the precedence list; it is the first one detected. The part of the precedence list which was successfully formed is also listed.
CLIPS> (defclass A (is-a MULTIFIELD FLOAT SYMBOL)) CLIPS> (defclass B (is-a SYMBOL FLOAT)) CLIPS> (defclass C (is-a A B))
The INSTANCE, INSTANCE NAME, and INSTANCE ADDRESS classes cannot have any subclasses.
CLIPS> (defclass A (is-a INSTANCE))
The evaluation of an expression yielded something other than a recognized class or primitive type.
This error occurs when an instance definition is improperly formed in the input file for the load instances, restore instances, or bload instances command.
CLIPS> (load-instances bogus.txt) [INSFILE2] <file name> file is not a binary instances file. or [INSFILE3] <file name> file is not a compatible binary instances file. This error occurs when bload instances attempts to load a file that was not created with bsave instances or when the file being loaded was created by a different version of CLIPS.
CLIPS> (reset) CLIPS> (save-instances foo.ins) 1 CLIPS> (bload-instances foo.ins)
This error occurs when an instance specification in the input file for the bload instances command could not be created.
CLIPS> (defclass A (is-a USER) (role concrete)) CLIPS> (make-instance of A) [gen1] CLIPS> (bsave-instances foo.bin) 1 CLIPS> (clear) CLIPS> (defclass A (is-a USER)) CLIPS> (bload-instances foo.bin)
The named function expected an instance name or address as an argument.
CLIPS> (initialize-instance 34)
This error occurs when the named function cannot find the specified instance.
CLIPS> (instance-address [bogus-instance]) [INSFUN3] No such slot <name> in function <name>. This error occurs when the named function cannot find the specified slot in an instance or class.
CLIPS> (defclass A (is-a USER)) CLIPS> (slot-writablep A b)
This error occurs when an attempt is made to use the address of a deleted instance.
CLIPS> (defclass A (is-a USER)) CLIPS> (make-instance a of A) [a] CLIPS> (defglobal ?*x* = (instance-address a)) CLIPS> (make-instance a of A) [a] CLIPS> (class ?*x*)
CLIPS does not allow reactive instance slots to be changed while pattern matching is taking place. Functions used on the LHS of a rule should not have side effects (such as the changing slot values).
CLIPS> (defclass FOO (is-a USER) (role concrete) (pattern-match reactive) (slot x (create-accessor read-write))) CLIPS> (make-instance x of FOO) [x] CLIPS> (defrule BAR (x) (test (send [x] put-x 3)) ⇒) CLIPS> (assert (x))
This error occurs when the number of simultaneous class hierarchy traversals is exceeded while pattern matching on a shared slot. See the related error message [CLASSFUN2] for more details.
Single field slots in an instance can hold only one atomic value.
CLIPS> (set-static-constraint-checking FALSE) TRUE CLIPS> (defclass FOO (is-a USER) (role concrete) (slot foo)) CLIPS> (defmessage-handler FOO error () (bind ?self:foo 1 2 3)) CLIPS> (make-instance foo of FOO) [foo] CLIPS> (send [foo] error)
Only functions which have a return value can be used to generate values for an instance slot.
CLIPS> (set-static-constraint-checking FALSE) TRUE CLIPS> (defclass FOO (is-a USER) (role concrete) (slot foo)) CLIPS> (defmessage-handler FOO error () (bind ?self:foo (instances))) CLIPS> (make-instance foo of FOO) [foo] CLIPS> (send [foo] error)
make instance expects a symbol or an instance name for the name of a new instance.
CLIPS> (make-instance 34 of A)
make instance expects a symbol for the class of a new instance.
CLIPS> (make-instance a of 34)
Direct instances of abstract classes, such as the predefined system classes, are illegal.
CLIPS> (make-instance [foo] of USER) [INSMGNR4] The instance <name> has a slot value which depends on the instance definition. The initialization of an instance is recursive in that a slot override or default value tries to create or reinitialize the same instance.
CLIPS> (defclass A (is-a USER) (slot foo)) CLIPS> (make-instance a of A (foo (make-instance a of A)))
make instance will attempt to delete an old instance of the same name if it exists. This error occurs if that deletion fails.
CLIPS> (defclass A (is-a USER)) CLIPS> (defmessage-handler A delete around () (if (neq (instance-name ?self) [a]) then (call-next-handler))) CLIPS> (make-instance a of A) CLIPS> (make-instance a of A)
The evaluation of a slot override in make instance or initialize instance attempted to delete the instance.
CLIPS> (defclass A (is-a USER) (slot foo)) CLIPS> (defmessage-handler A put-foo after ($?any) (delete-instance)) CLIPS> (make-instance a of A (foo 2))
An instance cannot be reinitialized during initialization.
CLIPS> (defclass A (is-a USER)) CLIPS> (make-instance a of A) CLIPS> (defmessage-handler A init after () (initialize-instance ?self)) CLIPS> (initialize-instance a) CLIPS> (send [a] try)
This message is displayed when an evaluation error occurs while the init message is executing for an instance.
make instance and initialize instance expect symbols for slot names.
CLIPS> (defclass A (is-a USER)) CLIPS> (make-instance a of A (34 override-value))
CLIPS does not allow instances of reactive classes to be created while pattern matching is taking place. Functions used on the LHS of a rule should not have side effects (such as the creation of a new instance or fact).
CLIPS> (defclass FOO (is-a USER) (role concrete) (pattern-match reactive)) CLIPS> (defrule BAR (x) (test (make-instance of FOO)) ⇒) CLIPS> (assert (x))
This error occurs when the module specifier in the instance name is illegal (such as an undefined module name).
CLIPS> (defclass FOO (is-a USER) (role concrete)) CLIPS> (make-instance BOGUS::x of FOO)
CLIPS does not allow instances of reactive classes to be deleted while pattern matching is taking place. Functions used on the LHS of a rule should not have side effects (such as the deletion of a new instance or the retraction of a fact).
CLIPS> (defclass FOO (is-a USER) (role concrete) (pattern-match reactive)) CLIPS> (make-instance x of FOO) [x] CLIPS> (defrule BAR (x) (test (send [x] delete)) ⇒) CLIPS> (assert (x))
This error occurs when the slot name of a slot override does not correspond to any of the valid slot names for an instance.
CLIPS> (defclass FOO (is-a USER) (role concrete)) CLIPS> (make-instance of FOO (x 3))
If the ?NONE keyword was specified with the default attribute for a slot, then a slot override must be provided when an instance containing that slot is created.
CLIPS> (defclass FOO (is-a USER) (role concrete) (slot x (default ?NONE))) CLIPS> (make-instance of FOO)
The special function init slots (for initializing slots of an instance to the class default values) can only be called during the dispatch of an init message for an instance, i.e., in an init message handler.
CLIPS> (defmessage-handler INITIAL-OBJECT error () (init-slots)) CLIPS> (reset) CLIPS> (send [initial-object] error)
The direct modify and message modify message handlers attached to the class USER can only be called as a result of the appropriate message being sent.by the modify instance or message modify instance functions. Additional handlers may be defined, but the message can only be sent in this context.
CLIPS> (reset) CLIPS> (send [initial-object] direct-modify 0)
The direct duplicate and message duplicate message handlers attached to the class USER can only be called as a result of the appropriate message being sent.by the duplicate instance or message duplicate instance functions. Additional handlers may be defined, but the message can only be sent in this context.
CLIPS> (reset) CLIPS> (send [initial-object] direct-duplicate 0 0)
If an instance name is specified for the new instance in the call to duplicate instance, it must be different from the source instance’s name.
CLIPS> (reset) CLIPS> (duplicate-instance initial-object to initial-object) [INSMULT1] Function <name> cannot be used on single field slot <name> in instance <name>. The functions described in section 12.13.4.12, such as slot insert$, can only operate on multifield slots.
CLIPS> (defclass A (is-a USER) (slot foo)) CLIPS> (make-instance a of A) [a] CLIPS> (slot-insert$ a foo 1 abc def)
Instance set member variables in an instance set query function must be unique.
CLIPS> (any-instancep ((?a OBJECT) (?a OBJECT)) TRUE)
An instance set query cannot bind variables.
CLIPS> (any-instancep ((?a OBJECT) (?b OBJECT)) (bind ?c 1))
Instance set member variables cannot be changed within the actions of an instance set query function.
CLIPS> (do-for-all-instances ((?a USER)) (if (slot-existp ?a age) then (> ?a:age 30)) (bind ?a (send ?a get-brother)))
A logical name must be either a symbol, string, instance name, float, or integer.
(printout (create$ a b c) x)
A logical name cannot be associated with two different files.
CLIPS> (open “foo.txt” foo “w”) TRUE CLIPS> (open “foo2.txt” foo “w”)
This error indicates insufficient memory exists to expand internal structures enough to allow continued operation (causing an exit to the operating system).
This error indicates a problem in the memory management routines.
This error occurs when the bload function attempts to allocate a block of memory larger than 32K and the operating system does not permit blocks greater than 32K to be allocated. This will only occur on machines which have 2 byte integers (excluding the Macintosh and IBM PC which have machine dependent code provided so that they can allocate more than 32K). When this error occurs, CLIPS exits to the operating system.
The expand$ function may not be called unless it is within the argument list of another function.
CLIPS> (expand$ (create$ a b c))
The module specifier can only be used as part of a defined construct’s name or as an argument to a function.
CLIPS> (deffunction y ()) CLIPS> (MAIN::y)
or [MODULPSR1] Module <module name> does not export any <construct type> constructs. or [MODULPSR1] Module <module name> does not export the <construct type> <construct name>. A construct cannot be imported from a module unless the defmodule exports that construct.
CLIPS> (clear) CLIPS> (defmodule BAR) CLIPS> (deftemplate BAR::bar) CLIPS> (defmodule FOO (import BAR deftemplate bar)))
It is illegal to specify a non wildcard handler index when a wildcard is given for the class in the external C function UndefmessageHandler(). This error can only be generated when a user defined external function linked with CLIPS calls this function incorrectly.
This error occurs when the named function cannot find the specified message handler.
CLIPS> (ppdefmessage-handler USER foo around)
This error occurs when a message handler can’t be deleted (such as when a binary image is loaded).
CLIPS> (defclass FOO (is-a USER) (role concrete)) CLIPS> (defmessage-handler FOO bar ()) CLIPS> (bsave foo.bin) TRUE CLIPS> (bload foo.bin) TRUE CLIPS> (undefmessage-handler FOO bar)
No primary message handler attached to the object’s classes matched the name of the message.
CLIPS> (defclass A (is-a USER)) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] bogus-message)
The number of message arguments was inappropriate for one of the applicable message handlers.
CLIPS> (defclass A (is-a USER)) CLIPS> (defmessage-handler USER foo (?a ?b)) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] foo)
This error occurs when an attempt is made to change the value of a read only slot.
CLIPS> (defclass A (is-a USER) (slot foo (default 100) (read-only))) CLIPS> (make-instance a of A) [a] CLIPS> (send [a] put-foo)
The named function operates on the active instance of a message and thus can only be called by message handlers.
CLIPS> (ppinstance)
The named function operates on the active instance of a message and can only handle instances of user defined classes (not primitive type objects).
CLIPS> (defmessage-handler INTEGER print () (ppinstance)) CLIPS> (send 34 print)
A subclass which inherits private slots from a superclass may not access those slots using the ?self variable. This error can also occur when a superclass tries to access via dynamic put or dynamic get a private slot in a subclass.
CLIPS> (defclass FOO (is-a USER) (role concrete) (slot x)) CLIPS> (defclass BAR (is-a FOO)) CLIPS> (defmessage-handler BAR yak () ?self:x)
Allowed message handler types include primary, before, after, and around.
CLIPS> (defmessage-handler USER foo behind ())
This error occurs when an attempt is made to delete a message handler attached to a class for which any of the message handlers are executing.
CLIPS> (reset) CLIPS> (defmessage-handler INITIAL-OBJECT error () (undefmessage-handler INITIAL-OBJECT error primary)) CLIPS> (send [initial-object] error)
No shadowed message handler is available when the functioncall next handler or override next handler is called.
CLIPS> (call-next-handler)
This error occurs when the named function cannot find the specified instance.
CLIPS> (instance-address [bogus-instance])
This error occurs when a static reference to a slot in a superclass by a message handler attached to that superclass is incorrectly applied to an instance of a subclass which redefines that slot. Static slot references always refer to the slot defined in the class to which the message handler is attached.
CLIPS> (defclass A (is-a USER) (slot foo)) CLIPS> (defclass B (is-a A) (role concrete) (slot foo)) CLIPS> (defmessage-handler A access-foo () ?self:foo) CLIPS> (make-instance b of B) [b] CLIPS> (send [b] access-foo)
A message handler can only be attached to an existing class.
CLIPS> (defmessage-handler bogus-class foo ())
No message handlers for a class can be loaded while any current message handlers attached to the class are executing.
CLIPS> (defclass A (is-a USER)) CLIPS> (make-instance a of A) [a] CLIPS> (defmessage-handler A build-new () (build “(defmessage-handler A new ())”)) CLIPS> (send [a] build-new)
There are four primary message handlers attached to the class USER which cannot be modified: init, delete, create and print.
CLIPS> (defmessage-handler USER init ())
Direct slot references are allowed only within message handler bodies.
CLIPS> (defmessage-handler USER foo (?self:bar))
?self is a reserved parameter for the active instance.
CLIPS> (defmessage-handler USER foo () (bind ?self 1))
The symbol following the ?self: reference must be a valid slot for the class.
CLIPS> (defclass FOO (is-a USER) (role concrete) (slot x)) CLIPS> (defmessage-handler FOO bar () ?self:y)
The symbol following the ?self: reference must be a symbol.
CLIPS> (defclass FOO (is-a USER) (role concrete) (slot x)) CLIPS> (defmessage-handler FOO bar () ?self:7)
Message handlers cannot be attached to the INSTANCE, INSTANCE ADDRESS, or INSTANCE NAME classes.
CLIPS> (defmessage-handler INSTANCE foo ())
or [MULTIFUN1] Multifield index range <start>…<end> out of range 1..<end range> in function <name> This error occurs when a multifield manipulation function is passed a single index or range of indices that does not fall within the specified range of allowed indices.
CLIPS> (delete$ (create$ a b c) 4 4)
The field variable (if specified) cannot be rebound within the body of the progn$ function.
CLIPS> (progn$ (?field (create$ a)) (bind ?field 3))
No objects of existing classes could possibly satisfy the pattern. This error usually occurs when a restriction placed on the is a attribute is incompatible with slot restrictions before it in the pattern.
CLIPS> (defclass A (is-a INITIAL-OBJECT) (slot foo)) CLIPS> (defrule error (object (foo ?) (is-a ~A)) ⇒)
The restrictions on <attribute> are such that no objects of existing classes (which also satisfy preceding restrictions) could possibly satisfy the pattern.
CLIPS> (defrule error (object (bad-slot ?)) ⇒) [OBJRTBLD3] No objects of existing classes can satisfy pattern #<pattern num>. No objects of existing classes could possibly satisfy the pattern. This error occurs when the constraints for a slot as given in the defclass(es) are incompatible with the constraints imposed by the pattern.
CLIPS> (defclass FOO (is-a INITIAL-OBJECT) (slot bar (type INTEGER))) CLIPS> (defclass BAR (is-a INITIAL-OBJECT) (slot bar (type SYMBOL)) (slot woz)) CLIPS> (defrule error (x abc) (object (bar 100) (woz ?)) (y def) ⇒)
Only one restriction per attribute is allowed per object pattern.
CLIPS> (defrule error (object (is-a ?) (is-a ?)) ⇒)
Object patterns are applicable only to classes of objects which are already defined.
CLIPS> (defrule error (object (is-a BOGUS)) ⇒)
Currently active instance: <instance name> Problem resides in slot <slot name> field #<field index> Of pattern #<pattern number> in rule(s): <problem rules>+ This error pinpoints other evaluation errors associated with evaluating an expression within the object pattern network. The specific pattern and field of the problem rules are identified.
Certain keywords have special meaning to CLIPS and may not be used in situations that would cause an ambiguity.
CLIPS> (deftemplate exists (slot x))
Single and multifield variable constraints cannot be mixed in a field constraint (this restriction does not include variables passed to functions with the predicate or return value constraints).
CLIPS> (defrule foo (a ?x $?y ?x&~$?y) ⇒)
In a CLIPS configuration without deffunctions and/or generic functions, an attempt was made to call a deffunction or generic function from a binary image generated by the bsave command.
An evaluation error occurred while examining the arguments for a deffunction, generic function or message.
CLIPS> (defmethod foo (?a)) CLIPS> (foo (instances))
Local variables in the actions of a deffunction, method, message handler, or defrule must reference parameters, variables bound within the actions with the bind function, or variables bound on the LHS of a rule.
CLIPS> (defrule foo ⇒ (+ ?a 3))
This error occurs when the actions of a rule, deffunction, generic function method or message handler are prematurely aborted due to an error.
This error occurs when local variables in the actions of a deffunction, method, message handler, or defrule becomes unbound during execution as a result of calling the bind function with no arguments.
CLIPS> (deffunction foo () (bind ?a) ?a) CLIPS> (foo)
An evaluation error occurred while examining the arguments for a deffunction, generic function method or message handler.
CLIPS> (deffunction foo (?a)) CLIPS> (foo (+ (eval “(gensym)”) 2))
Deffunction, method or message handler parameter names must be unique.
CLIPS> (defmethod foo ((?x INTEGER) (?x FLOAT)))
A wildcard parameter for a deffunction, method or message handler must be the last parameter.
CLIPS> (defmethod foo (($?x INTEGER) (?y SYMBOL)))
The special variable ?count cannot be rebound within the body of the loop for count function.
CLIPS> (loop-for-count (?count 10) (bind ?count 3))
or [PRCDRPSR2] The break function is not valid in this context. The return and break functions can only be used within certain contexts (e.g. the break function can only be used within a while loop and certain instance set query functions).
CLIPS> (return 3)
A case may be specified only once in a switch statement.
CLIPS> (switch a (case a then 8) (case a then 9))
This error occurs when CLIPS cannot find the named item (check for typos).
This error occurs when the appropriate syntax is not used.
CLIPS> (if (> 3 4))
*** CLIPS SYSTEM ERROR *** ID = <error id> CLIPS data structures are in an inconsistent or corrupted state. This error may have occurred from errors in user defined code. ************************** This error indicates an internal problem within CLIPS (which may have been caused by user defined functions or other user code). If the problem cannot be located within user defined code, then the <error id> should be reported.
This error occurs when CLIPS cannot delete the named item (e.g. a construct might be in use). One example which will cause this error is an attempt to delete a deffunction or generic function which is used in another construct (such as the RHS of a defrule or a default dynamic facet of a defclass slot).
This error occurs when CLIPS has already parsed an attribute or declaration.
This error occurs when a local variable is used by a function or construct that cannot use global variables.
CLIPS> (deffacts info (fact ?x))
This error occurs when a function attempts to divide by zero.
CLIPS> (/ 3 0)
This error results because “Hello” is not recognized as a valid router name.
CLIPS> (printout “Hello” crlf)
has constraint conflicts which make the pattern unmatchable. or [RULECSTR1] Variable <variable name> in CE #<integer> field #<integer> has constraint conflicts which make the pattern unmatchable. or [RULECSTR1] CE #<integer> slot <slot name> has constraint conflicts which make the pattern unmatchable. or [RULECSTR1] CE #<integer> field #<integer> has constraint conflicts which make the pattern unmatchable. This error occurs when slot value constraints (such as allowed types) prevents any value from matching the slot constraint for a pattern.
CLIPS> (deftemplate foo (slot x (type SYMBOL))) CLIPS> (deftemplate bar (slot x (type FLOAT))) CLIPS> (defrule yak (foo (x ?x)) (bar (x ?x)) ⇒)
for argument #<integer> of the expression <expression> found in CE#<integer> slot <slot name> to be violated. This error occurs when previous variable bindings and constraints prevent a variable from containing a value which satisfies the type constraints for one of a function’s parameters.
CLIPS> (deftemplate foo (slot x (type SYMBOL))) CLIPS> (defrule bar (foo (x ?x&:(> ?x 3))) ⇒)
for argument #<integer> of the expression <expression> found in the rule's RHS to be violated. This error occurs when previous variable bindings and constraints prevent a variable from containing a value which satisfies the type constraints for one of a function’s parameters.
CLIPS> (deftemplate foo (slot x (type SYMBOL))) CLIPS> (defrule bar (foo (x ?x)) ⇒ (printout t (+ ?x 1) crlf))
Logical CEs can be placed outside, but not inside, a not/exists/forall CE.
CLIPS> (defrule error (not (logical (x))) ⇒)
This is an illegal operation and results in an error message.
CLIPS> (defrule error (not ?f ← (fact)) ⇒)
If logical CEs are used, then the first CE must be a logical CE.
CLIPS> (defrule error (a) (logical (b)) ⇒)
Logical CEs found within a rule must be contiguous.
CLIPS> (defrule error (logical (a)) (b) (logical ©) ⇒) [STRNGFUN1] Function build does not work in run time modules. or [STRNGFUN1] Function eval does not work in run time modules. The build and eval functions do not work in run time modules because the code required for parsing is not available.
Local variables cannot be accessed by the eval function.
CLIPS> (eval “?x”)
This message occurs if the f option is used when executing CLIPS, but no arguments are provided.
clips -f
This error occurs when the external text processing system cannot open the specified help file, e.g., the file cannot be found or the CLIPS process does not have sufficient privileges to read the file.
CLIPS> (help-path “bogus.txt”) CLIPS. (help)
This error occurs when the external text processing system command fetch encounters an error when loading a file.
CLIPS> (fetch “bogus.txt”)
The slot name supplied does not correspond to a slot name defined in the corresponding deftemplate
CLIPS> (deftemplate example (slot x)) CLIPS> (defrule error (example (z 3)) ⇒)
If a slot definition is specified in a template pattern or fact, the contents of the slot must be capable of matching against or evaluating to a single value.
CLIPS> (deftemplate example (slot x)) CLIPS> (assert (example (x)))
Fact indexes may only be used with the modify and duplicate commands when the command is issued from the top level command prompt.
CLIPS> (defrule foo ⇒ (modify 1 (x 3))
A multifield value cannot be stored in a single field slot.
CLIPS> (deftemplate foo (slot x)) CLIPS> (defrule foo ⇒ (bind ?x (create$ a b)) (assert (foo (x ?x)))) CLIPS> (reset) CLIPS> (run)
The (default ?NONE) attribute requires that a slot value be supplied whenever a new fact is created.
CLIPS> (deftemplate foo (slot x (default ?NONE))) CLIPS> (assert (foo)) Appendix H CLIPS BNFData Types
in section 2.3.1
in section 2.3.1
in section 2.3.1
in section 2.3.1
in section 2.3.1
<float> | <instance name>
alphabetic character
system or user defined function, a deffunction name, or a defgeneric name
file name (including path information) for the operating system under which CLIPS is running
indicate what the symbol represents. For example, <rule-name> is a symbol which represents the name of a rule. Variables and Expressions
<multifield-variable> | <global-variable>
<function-call>
the type indicated by the ellipsis. For example, <integer-expression> should return an integer. Constructs
<deftemplate-construct> | <defglobal-construct> | <defrule-construct> | <deffunction-construct> | <defgeneric-construct> | <defmethod-construct> | <defclass-construct> | <definstance-construct> | <defmessage-handler-construct> | <defmodule-construct> Deffacts Construct
Deftemplate Construct
::= (deftemplate <deftemplate-name> [<comment>] <slot-definition>*)
<multislot-definition>
::= (slot <slot-name> <template-attribute>*)
::= (multislot <slot-name> <template-attribute>*)
::= <default-attribute> | <constraint-attribute>
::= (default ?DERIVE | ?NONE | <expression>*) | (default-dynamic <expression>*) Fact Specification
<template-RHS-pattern>
<multifield-RHS-slot>
<constant> | <function-call> Defrule Construct
[<declaration>]
<conditional-element>* <declaration> ::= (declare <rule-property>+)
(auto-focus <boolean-symbol>) <boolean-symbol> ::= TRUE | FALSE
<assigned-pattern-CE> | <not-CE> | <and-CE> | <or-CE> | <logical-CE> | <test-CE> | <exists-CE> | <forall-CE>
<template-pattern-CE> | <object-pattern-CE>
<or-CE> ::= (or <conditional-element>+)
<conditional-element>+)
(name <constraint>) | (<slot-name> <constraint>*)
<multifield-LHS-slot>
::= <single-constraint> | <single-constraint> & <connected-constraint> | <single-constraint> | <connected-constraint>
<single-field-variable> | <multifield-variable> | :<function-call> | =<function-call> Defglobal Construct <defglobal-construct> ::= (defglobal [<defmodule-name>] <global-assignment>*)
Deffunction Construct
::= (deffunction <name> [<comment>] (<regular-parameter>* [<wildcard-parameter>]) <action>*)
Defgeneric Construct
Defmethod Construct
::= (defmethod <name> [<index>] [<comment>] (<parameter-restriction>* [<wildcard-parameter-restriction>]) <action>*)
::= <single-field-variable> | (<single-field-variable> <type>* [<query>])
::= <multifield-variable> | (<multifield-variable> <type>* [<query>])
Defclass Construct
(is-a <superclass-name>+) [<role>] [<pattern-match-role>] <slot>* <handler-documentation>*)
::= (pattern-match reactive | non-reactive)
(single-slot <name> <facet>*) | (multislot <name> <facet>*)
<access-facet> | <propagation-facet> | <source-facet> | <pattern-match-facet> | <visibility-facet> | <create-accessor-facet> <override-message-facet> | <constraint-attribute> <default-facet> ::= (default ?DERIVE | ?NONE | <expression>*) | (default-dynamic <expression>*)
::= (access read-write | read-only | initialize-only)
::= (pattern-match reactive | non-reactive)
::= (create-accessor ?NONE | read | write | read-write)
::= (override-message ?DEFAULT | <message-name>) <handler-documentation> ::= (message-handler <name> [<handler-type>])
Defmessage-handler Construct
::= (defmessage-handler <class-name> <message-name> [<handler type>] [<comment>] (<parameter>* [<wildcard-parameter>]) <action>*)
Definstances Construct
::= (definstances <definstances-name> [active] [<comment>] <instance-template>*)
Defmodule Construct
<port-specification>*)
(import <module-name> <port-item>)
?NONE | <port-construct> ?ALL | <port-construct> ?NONE | <port-construct> <construct-name>+
defglobal | deffunction | defgeneric Constraint Attributes
::= <type-attribute> | <allowed-constant-attribute> | <range-attribute> | <cardinality-attribute> <type-attribute> ::= (type <type-specification>)
INTEGER | FLOAT | NUMBER | INSTANCE-NAME | INSTANCE-ADDRESS | INSTANCE | EXTERNAL-ADDRESS | FACT-ADDRESS
::= (allowed-symbols <symbol-list>) | (allowed-strings <string-list>) | (allowed-lexemes <lexeme-list> | (allowed-integers <integer-list>) | (allowed-floats <float-list>) | (allowed-numbers <number-list>) | (allowed-instance-names <instance-list>) | (allowed-values <value-list>)
<range-specification>)
::= (cardinality <cardinality-specification> <cardinality-specification>)
::= <integer> | ?VARIABLE
Appendix I Reserved Function NamesThis appendix lists all of the functions provided by either standard CLIPS or various CLIPS extensions. They should be considered reserved function names, and users should not create user defined functions with any of these names.
* ** + - / < ⇐ <> =
abs acos acosh acot acoth acsc acsch active duplicate instance active-initialize-instance active-make-instance active message duplicate instance active-message-modify-instance active-modify-instance agenda and any-instancep apropos asec asech asin asinh assert assert-string atan atanh batch batch* bind bload bload-instances break browse-classes bsave bsave-instances build call-next-handler call-next-method call-specific-method class class-abstractp class-existp class-reactivep class-slots class-subclasses class-superclasses clear clear-focus-stack close conserve-mem constructs-to-c cos cosh cot coth create$ csc csch defclass-module deffacts-module deffunction-module defgeneric-module defglobal-module definstances-module defrule-module deftemplate-module deg-grad deg-rad delayed-do-for-all-instances delete$ delete-instance dependencies dependents describe-class direct-mv-delete direct-mv-insert direct-mv-replace div do-for-all-instances do-for-instance dribble-off dribble-on duplicate duplicate-instance duplicate-instance dynamic-get dynamic-put edit eq eval evenp exit exp expand$ explode$ fact-existp fact-index fact-relation fact-slot-names fact-slot-value facts fetch find-all-instances find-instance first$ float floatp focus format gensym gensym* get get-auto-float-dividend get-current-module get-defclass-list get-deffacts-list get-deffunction-list get-defgeneric-list get-defglobal-list get-definstances-list get-defmessage-handler-list get-defmethod-list get-defmodule-list get-defrule-list get-deftemplate-list get-dynamic-constraint-checking get-fact-duplication get-fact-list get-focus get-focus-stack get-function-restrictions get-incremental-reset get-method-restrictions get-reset-globals get-salience-evaluation get-sequence-operator-recognition get-static-constraint-checking get-strategy grad-deg halt help help-path if implode$ init-slots initialize-instance initialize-instance insert$ instance-address instance-addressp instance-existp instance-name instance-name-to-symbol instance-namep instancep instances integer integerp length length$ lexemep list-defclasses list-deffacts list-deffunctions list-defgenerics list-defglobals list-definstances list-defmessage-handlers list-defmethods list-defmodules list-defrules list-deftemplates list-focus-stack list-watch-items load load* load-facts load-instances log log10 loop-for-count lowcase make-instance make-instance matches max mem-requests mem-used member member$ message-duplicate-instance message-duplicate-instance message-handler-existp message-modify-instance message-modify-instance min mod modify modify-instance modify-instance multifieldp mv-append mv-delete mv-replace mv-slot-delete mv-slot-insert mv-slot-replace mv-subseq neq next-handlerp next-methodp not nth nth$ numberp object-pattern-match-delay oddp open options or override-next-handler override-next-method pi pointerp pop-focus ppdefclass ppdeffacts ppdeffunction ppdefgeneric ppdefglobal ppdefinstances ppdefmessage-handler ppdefmethod ppdefmodule ppdefrule ppdeftemplate ppinstance preview-generic preview-send primitives-info print-region printout progn progn$ put rad-deg random read readline refresh refresh-agenda release-mem remove remove-break rename replace$ reset rest$ restore-instances retract return round rule-complexity rules run save save-facts save-instances sec sech seed send sequencep set-auto-float-dividend set-break set-current-module set-dynamic-constraint-checking set-fact-duplication set-incremental-reset set-reset-globals set-salience-evaluation set-sequence-operator-recognition set-static-constraint-checking set-strategy setgen show-breaks show-defglobals show-fht show-fpn show-joins show-opn sin sinh slot allowed values slot-cardinality slot-delete$ slot-direct-accessp slot-direct-delete$ slot-direct-insert$ slot-direct-replace$ slot-existp slot-facets slot-initablep slot-insert$ slot-publicp slot-range slot-replace$ slot-sources slot-types slot-writablep sqrt str-assert str-cat str-compare str-explode str-implode str-index str-length stringp sub-string subclassp subseq$ subset subsetp superclassp switch sym-cat symbol-to-instance-name symbolp system tan tanh time toss type type undefclass undeffacts undeffunction undefgeneric undefglobal undefinstances undefmessage-handler undefmethod undefrule undeftemplate unmake-instance unwatch upcase watch while wordp Appendix J Bibliography of CLIPS PublicationsProgramming
Reviews
Overviews
Applications
Enhancements/Implementation
Rete Pattern Matching Algorithm
|