Reference Manual

 

Volume I

Basic Programming Guide

 

 

Quicksilver Beta

December 31st 2007

 

 

 

 

 


CLIPS Basic Programming Guide

Quicksilver Beta  December 31st 2007

 

CONTENTS

License Information....................................................................................................................... i

Preface............................................................................................................................................ iii

Acknowledgements...................................................................................................................... vii

Section 1 ‑ Introduction................................................................................................................ 1

Section 2 ‑ CLIPS Overview......................................................................................................... 3

2.1 Interacting with CLIPS........................................................................................................ 3

2.1.1 Top Level Commands................................................................................................. 3

2.1.2 Automated Command Entry and Loading................................................................... 4

2.1.3 Integration with Other Languages............................................................................... 5

2.2 Reference Manual Syntax.................................................................................................... 5

2.3 Basic Programming Elements.............................................................................................. 6

2.3.1 Data Types.................................................................................................................. 6

2.3.2 Functions.................................................................................................................... 9

2.3.3 Constructs................................................................................................................. 10

2.4 Data Abstraction................................................................................................................ 10

2.4.1 Facts.......................................................................................................................... 11

2.4.1.1 Ordered Facts................................................................................................... 11

2.4.1.2 Non‑ordered Facts........................................................................................... 12

2.4.1.3 Initial Facts....................................................................................................... 13

2.4.2 Objects...................................................................................................................... 13

2.4.2.1 Initial Objects................................................................................................... 14

2.4.3 Global Variables....................................................................................................... 14

2.5 Knowledge Representation................................................................................................ 15

2.5.1 Heuristic Knowledge – Rules................................................................................... 15

2.5.2 Procedural Knowledge.............................................................................................. 16

2.5.2.1 Deffunctions.................................................................................................... 16

2.5.2.2 Generic Functions............................................................................................ 16

2.5.2.3 Object Message‑Passing.................................................................................. 17

2.5.2.4 Defmodules...................................................................................................... 17

2.6 CLIPS Object‑Oriented Language..................................................................................... 17

2.6.1 COOL Deviations from a Pure OOP Paradigm........................................................ 17

2.6.2 Primary OOP Features.............................................................................................. 18

2.6.3 Instance‑set Queries and Distributed Actions........................................................... 19

Section 3 ‑ Deftemplate Construct............................................................................................. 21

3.1 Slot Default Values............................................................................................................ 22

3.2 Slot Default Constraints for Pattern‑Matching................................................................... 22

3.3 Slot Value Constraint Attributes........................................................................................ 23

3.4 Implied Deftemplates......................................................................................................... 23

Section 4 ‑ Deffacts Construct.................................................................................................... 25

Section 5 ‑ Defrule Construct..................................................................................................... 27

5.1 Defining Rules................................................................................................................... 27

5.2 Basic Cycle Of Rule Execution.......................................................................................... 28

5.3 Conflict Resolution Strategies............................................................................................ 29

5.3.1 Depth Strategy.......................................................................................................... 29

5.3.2 Breadth Strategy........................................................................................................ 29

5.3.3 Simplicity Strategy.................................................................................................... 29

5.3.4 Complexity Strategy.................................................................................................. 30

5.3.5 LEX Strategy............................................................................................................ 30

5.3.6 MEA Strategy........................................................................................................... 31

5.3.7 Random Strategy....................................................................................................... 31

5.4 LHS Syntax....................................................................................................................... 33

5.4.1 Pattern Conditional Element...................................................................................... 33

5.4.1.1 Literal Constraints............................................................................................ 34

5.4.1.2 Wildcards Single‑ and Multifield..................................................................... 36

5.4.1.3 Variables Single‑ and Multifield...................................................................... 38

5.4.1.4 Connective Constraints.................................................................................... 40

5.4.1.5 Predicate Constraints........................................................................................ 43

5.4.1.6 Return Value Constraints................................................................................. 45

5.4.1.7 Pattern‑Matching with Object Patterns............................................................. 46

5.4.1.8 Pattern‑Addresses............................................................................................ 49

5.4.2 Test Conditional Element.......................................................................................... 49

5.4.3 Or Conditional Element............................................................................................. 51

5.4.4 And Conditional Element.......................................................................................... 52

5.4.5 Not Conditional Element........................................................................................... 53

5.4.6 Exists Conditional Element....................................................................................... 54

5.4.7 Forall Conditional Element........................................................................................ 56

5.4.8 Logical Conditional Element..................................................................................... 58

5.4.9 Automatic Addition and Reordering of LHS CEs..................................................... 61

5.4.9.1 Rules Without Any LHS Pattern CEs.............................................................. 61

5.4.9.2 Test and Not CEs as the First CE of an And CE.............................................. 61

5.4.9.3 Test CEs Following Not CEs........................................................................... 62

5.4.9.4 Or CEs Following Not CEs............................................................................. 63

5.4.9.5 Notes About Pattern Addition and Reordering................................................ 63

5.4.10 Declaring Rule Properties....................................................................................... 63

5.4.10.1 The Salience Rule Property............................................................................ 64

5.4.10.2 The Auto‑Focus Rule Property...................................................................... 65

Section 6 ‑ Defglobal Construct.................................................................................................. 67

Section 7 ‑ Deffunction Construct.............................................................................................. 73

Section 8 ‑ Generic Functions..................................................................................................... 75

8.1 Note on the Use of the Term Method................................................................................. 75

8.2 Performance Penalty of Generic Functions........................................................................ 76

8.3 Order Dependence of Generic Function Definitions.......................................................... 76

8.4 Defining a New Generic Function..................................................................................... 76

8.4.1 Generic Function Headers......................................................................................... 77

8.4.2 Method Indices......................................................................................................... 77

8.4.3 Method Parameter Restrictions................................................................................. 78

8.4.4 Method Wildcard Parameter...................................................................................... 79

8.5 Generic Dispatch................................................................................................................ 81

8.5.1 Applicability of Methods Summary.......................................................................... 81

8.5.2 Method Precedence................................................................................................... 82

8.5.3 Shadowed Methods.................................................................................................. 85

8.5.4 Method Execution Errors.......................................................................................... 85

8.5.5 Generic Function Return Value................................................................................. 85

Section 9 ‑ CLIPS Object Oriented Language (COOL)........................................................... 87

9.1 Background........................................................................................................................ 87

9.2 Predefined System Classes................................................................................................ 87

9.3 Defclass Construct............................................................................................................. 88

9.3.1 Multiple Inheritance.................................................................................................. 89

9.3.1.1 Multiple Inheritance Rules............................................................................... 90

9.3.2 Class Specifiers......................................................................................................... 92

9.3.2.1 Abstract and Concrete Classes......................................................................... 92

9.3.2.2 Reactive and Non‑Reactive Classes................................................................. 92

9.3.3 Slots.......................................................................................................................... 92

9.3.3.1 Slot Field Type................................................................................................. 93

9.3.3.2 Default Value Facet.......................................................................................... 93

9.3.3.3 Storage Facet.................................................................................................... 94

9.3.3.4 Access Facet.................................................................................................... 95

9.3.3.5 Inheritance Propagation Facet.......................................................................... 96

9.3.3.6 Source Facet..................................................................................................... 97

9.3.3.7 Pattern‑Match Reactivity Facet......................................................................... 98

9.3.3.8 Visibility Facet................................................................................................. 99

9.3.3.9 Create‑Accessor Facet.................................................................................... 100

9.3.3.10 Override‑Message Facet.............................................................................. 101

9.3.3.11 Constraint Facets.......................................................................................... 101

9.3.4 Message‑handler Documentation............................................................................ 102

9.4 Defmessage‑handler Construct........................................................................................ 103

9.4.1 Message‑handler Parameters................................................................................... 105

9.4.1.1 Active Instance Parameter.............................................................................. 105

9.4.2 Message‑handler Actions........................................................................................ 106

9.4.3 Daemons................................................................................................................. 108

9.4.4 Predefined System Message‑handlers..................................................................... 108

9.4.4.1 Instance Initialization...................................................................................... 108

9.4.4.2 Instance Deletion............................................................................................ 109

9.4.4.3 Instance Display............................................................................................. 110

9.4.4.4 Directly Modifying an Instance...................................................................... 110

9.4.4.5 Modifying an Instance using Messages......................................................... 111

9.4.4.6 Directly Duplicating an Instance.................................................................... 111

9.4.4.7 Duplicating an Instance using Messages........................................................ 112

9.4.4.8 Instance Creation............................................................................................ 112

9.5 Message Dispatch............................................................................................................ 112

9.5.1 Applicability of Message‑handlers.......................................................................... 113

9.5.2 Message‑handler Precedence.................................................................................. 113

9.5.3 Shadowed Message‑handlers.................................................................................. 114

9.5.4 Message Execution Errors...................................................................................... 114

9.5.5 Message Return Value............................................................................................ 115

9.6 Manipulating Instances.................................................................................................... 115

9.6.1 Creating Instances................................................................................................... 115

9.6.1.1 Definstances Construct.................................................................................. 117

9.6.2 Reinitializing Existing Instances.............................................................................. 118

9.6.3 Reading Slots.......................................................................................................... 120

9.6.4 Setting Slots............................................................................................................ 120

9.6.5 Deleting Instances................................................................................................... 121

9.6.6 Delayed Pattern‑Matching When Manipulating Instances....................................... 121

9.6.7 Modifying Instances............................................................................................... 122

9.6.7.1 Directly Modifying an Instance with Delayed Pattern‑Matching................... 122

9.6.7.2 Directly Modifying an Instance with Immediate Pattern‑Matching................ 123

9.6.7.3 Modifying an Instance using Messages with Delayed Pattern‑Matching....... 123

9.6.7.4 Modifying an Instance using Messages with Immediate Pattern‑Matching... 124

9.6.8 Duplicating Instances.............................................................................................. 124

9.6.8.1 Directly Duplicating an Instance with Delayed Pattern‑Matching.................. 124

9.6.8.2 Directly Duplicating an Instance with Immediate Pattern‑Matching............... 125

9.6.8.3 Duplicating an Instance using Messages with Delayed Pattern‑Matching..... 125

9.6.8.4 Duplicating an Instance using Messages with Immediate Pattern‑Matching.. 126

9.7 Instance‑set Queries and Distributed Actions.................................................................. 127

9.7.1 Instance‑set Definition............................................................................................ 128

9.7.2 Instance‑set Determination...................................................................................... 129

9.7.3 Query Definition..................................................................................................... 130

9.7.4 Distributed Action Definition.................................................................................. 131

9.7.5 Scope in Instance‑set Query Functions................................................................... 132

9.7.6 Errors during Instance‑set Query Functions........................................................... 132

9.7.7 Halting and Returning Values from Query Functions............................................. 133

9.7.8 Instance‑set Query Functions.................................................................................. 133

9.7.8.1 Testing if Any Instance‑set Satisfies a Query................................................ 133

9.7.8.2 Determining the First Instance‑set Satisfying a Query................................... 133

9.7.8.3 Determining All Instance‑sets Satisfying a Query......................................... 134

9.7.8.4 Executing an Action for the First Instance‑set Satisfying a Query................. 134

9.7.8.5 Executing an Action for All Instance‑sets Satisfying a Query....................... 135

9.7.8.6 Executing a Delayed Action for All Instance‑sets       Satisfying a Query...... 135

Section 10 ‑ Defmodule Construct........................................................................................... 137

10.1 Defining Modules.......................................................................................................... 137

10.2 Specifying a Construct’s Module................................................................................... 138

10.3 Specifying Modules....................................................................................................... 139

10.4 Importing and Exporting Constructs.............................................................................. 139

10.4.1 Exporting Constructs............................................................................................ 140

10.4.2 Importing Constructs............................................................................................ 141

10.5 Importing and Exporting Facts and Instances................................................................ 141

10.5.1 Specifying Instance‑Names................................................................................... 142

10.6 Modules and Rule Execution......................................................................................... 142

Section 11 ‑ Constraint Attributes........................................................................................... 145

11.1 Type Attribute................................................................................................................ 145

11.2 Allowed Constant Attributes.......................................................................................... 146

11.3 Range Attribute.............................................................................................................. 147

11.4 Cardinality Attribute....................................................................................................... 147

11.5 Deriving a Default Value From Constraints................................................................... 148

11.6 Constraint Violation Examples....................................................................................... 149

Section 12 ‑ Actions And Functions......................................................................................... 151

12.1 Predicate Functions........................................................................................................ 151

12.1.1 Testing For Numbers............................................................................................ 151

12.1.2 Testing For Floats................................................................................................. 151

12.1.3 Testing For Integers.............................................................................................. 151

12.1.4 Testing For Strings Or Symbols........................................................................... 152

12.1.5 Testing For Strings............................................................................................... 152

12.1.6 Testing For Symbols............................................................................................. 152

12.1.7 Testing For Even Numbers................................................................................... 152

12.1.8 Testing For Odd Numbers.................................................................................... 152

12.1.9 Testing For Multifield Values............................................................................... 153

12.1.10 Testing For External‑Addresses.......................................................................... 153

12.1.11 Comparing for Equality....................................................................................... 153

12.1.12 Comparing for Inequality.................................................................................... 153

12.1.13 Comparing Numbers for Equality....................................................................... 154

12.1.14 Comparing Numbers for Inequality.................................................................... 154

12.1.15 Greater Than Comparison................................................................................... 155

12.1.16 Greater Than or Equal Comparison..................................................................... 155

12.1.17 Less Than Comparison....................................................................................... 156

12.1.18 Less Than or Equal Comparison......................................................................... 156

12.1.19 Boolean And....................................................................................................... 156

12.1.20 Boolean Or.......................................................................................................... 157

12.1.21 Boolean Not........................................................................................................ 157

12.2 Multifield Functions....................................................................................................... 157

12.2.1 Creating Multifield Values.................................................................................... 157

12.2.2 Specifying an Element........................................................................................... 158

12.2.3 Finding an Element............................................................................................... 158

12.2.4 Comparing Multifield Values................................................................................ 158

12.2.5 Deletion of Fields in Multifield Values................................................................. 159

12.2.6 Creating Multifield Values from Strings............................................................... 159

12.2.7 Creating Strings from Multifield Values............................................................... 160

12.2.8 Extracting a Sub‑sequence from a Multifield Value.............................................. 160

12.2.9 Replacing Fields within a Multifield Value........................................................... 161

12.2.10 Inserting Fields within a Multifield Value........................................................... 161

12.2.11 Getting the First Field from a Multifield Value................................................... 162

12.2.12 Getting All but the First Field from a Multifield Value....................................... 162

12.2.13 Determining the Number of Fields in a Multifield Value.................................... 162

12.2.14 Deleting Specific Values within a Multifield Value............................................ 162

12.2.15 Replacing Specific Values within a Multifield Value.......................................... 163

12.3 String Functions............................................................................................................. 163

12.3.1 String Concatenation............................................................................................. 163

12.3.2 Symbol Concatenation.......................................................................................... 164

12.3.3 Taking a String Apart............................................................................................ 164

12.3.4 Searching a String................................................................................................. 164

12.3.5 Evaluating a Function within a String................................................................... 165

12.3.6 Evaluating a Construct within a String.................................................................. 165

12.3.7 Converting a String to Uppercase......................................................................... 166

12.3.8 Converting a String to Lowercase......................................................................... 166

12.3.9 Comparing Two Strings........................................................................................ 166

12.3.10 Determining the Length of a String..................................................................... 167

12.3.11 Checking the Syntax of a Construct or Function Call within a String................. 167

12.3.12 Converting a String to a Field............................................................................. 168

12.4 The CLIPS I/O System.................................................................................................. 168

12.4.1 Logical Names...................................................................................................... 168

12.4.2 Common I/O Functions........................................................................................ 169

12.4.2.1 Open............................................................................................................ 169

12.4.2.2 Close............................................................................................................ 170

12.4.2.3 Printout........................................................................................................ 171

12.4.2.4 Read............................................................................................................. 171

12.4.2.5 Readline....................................................................................................... 172

12.4.2.6 Format.......................................................................................................... 173

12.4.2.7 Rename........................................................................................................ 175

12.4.2.8 Remove........................................................................................................ 175

12.4.2.9 Get Character............................................................................................... 176

12.4.2.10 Read Number............................................................................................. 177

12.4.2.11 Set Locale................................................................................................... 177

12.5 Math Functions.............................................................................................................. 178

12.5.1 Standard Math Functions...................................................................................... 178

12.5.1.1 Addition....................................................................................................... 178

12.5.1.2 Subtraction................................................................................................... 179

12.5.1.3 Multiplication............................................................................................... 179

12.5.1.4 Division....................................................................................................... 180

12.5.1.5 Integer Division........................................................................................... 180

12.5.1.6 Maximum Numeric Value............................................................................ 181

12.5.1.7 Minimum Numeric Value............................................................................ 181

12.5.1.8 Absolute Value............................................................................................ 181

12.5.1.9 Convert To Float.......................................................................................... 182

12.5.1.10 Convert To Integer..................................................................................... 182

12.5.2 Extended Math Functions..................................................................................... 182

12.5.2.1 Trigonometric Functions.............................................................................. 183

12.5.2.2 Convert From Degrees to Grads.................................................................. 184

12.5.2.3 Convert From Degrees to Radians............................................................... 184

12.5.2.4 Convert From Grads to Degrees.................................................................. 184

12.5.2.5 Convert From Radians to Degrees............................................................... 185

12.5.2.6 Return the Value of Ļ................................................................................... 185

12.5.2.7 Square Root................................................................................................. 185

12.5.2.8 Power........................................................................................................... 185

12.5.2.9 Exponential.................................................................................................. 186

12.5.2.10 Logarithm................................................................................................... 186

12.5.2.11 Logarithm Base 10..................................................................................... 186

12.5.2.12 Round........................................................................................................ 187

12.5.2.13 Modulus..................................................................................................... 187

12.6 Procedural Functions..................................................................................................... 187

12.6.1 Binding Variables................................................................................................. 187

12.6.2 If...then...else Function.......................................................................................... 189

12.6.3 While..................................................................................................................... 190

12.6.4 Loop-for-count...................................................................................................... 191

12.6.5 Progn.................................................................................................................... 191

12.6.6 Progn$.................................................................................................................. 192

12.6.7 Return................................................................................................................... 192

12.6.8 Break..................................................................................................................... 193

12.6.9 Switch................................................................................................................... 193

12.7 Miscellaneous Functions................................................................................................ 194

12.7.1 Gensym................................................................................................................. 194

12.7.2 Gensym*............................................................................................................... 195

12.7.3 Setgen................................................................................................................... 195

12.7.4 Random................................................................................................................. 196

12.7.5 Seed...................................................................................................................... 196

12.7.6 Time...................................................................................................................... 196

12.7.7 Number of Fields or Characters in a Data Object.................................................. 197

12.7.8 Determining the Restrictions for a Function.......................................................... 197

12.7.9 Sorting a List of Values........................................................................................ 197

12.7.10 Calling a Function............................................................................................... 198

12.7.11 Timing Functions and Commands...................................................................... 198

12.8 Deftemplate Functions................................................................................................... 199

12.8.1 Determining the Module in which a Deftemplate is Defined................................. 199

12.8.2 Getting the Allowed Values for a Deftemplate Slot.............................................. 199

12.8.3 Getting the Cardinality for a Deftemplate Slot....................................................... 199

12.8.4 Testing whether a Deftemplate Slot has a Default................................................. 200

12.8.5 Getting the Default Value for a Deftemplate Slot.................................................. 200

12.8.6 Deftemplate Slot Existence.................................................................................... 201

12.8.7 Testing whether a Deftemplate Slot is a Multifield Slot........................................ 201

12.8.8 Determining the Slot Names Associated with a Deftemplate................................ 202

12.8.9 Getting the Numeric Range for a Deftemplate Slot............................................... 202

12.8.10 Testing whether a Deftemplate Slot is a Single-Field Slot................................... 202

12.8.11 Getting the Primitive Types for a Deftemplate Slot............................................. 203

12.8.12 Getting the List of Deftemplates.......................................................................... 203

12.9 Fact Functions................................................................................................................ 203

12.9.1 Creating New Facts............................................................................................... 204

12.9.2 Removing Facts from the Fact‑list........................................................................ 204

12.9.3 Modifying Template Facts.................................................................................... 205

12.9.4 Duplicating Template Facts................................................................................... 206

12.9.5 Asserting a String................................................................................................. 206

12.9.6 Getting the Fact‑Index of a Fact‑address............................................................... 207

12.9.7 Determining If a Fact Exists.................................................................................. 207

12.9.8 Determining the Deftemplate (Relation) Name Associated with a Fact................. 208

12.9.9 Determining the Slot Names Associated with a Fact............................................. 208

12.9.10 Retrieving the Slot Value of a Fact...................................................................... 209

12.9.11 Retrieving the Fact-List....................................................................................... 209

12.9.12 Fact‑set Queries and Distributed Actions............................................................ 210

12.9.12.1 Fact‑set Definition...................................................................................... 211

12.9.12.2 Fact‑set Determination............................................................................... 212

12.9.12.3 Query Definition........................................................................................ 213

12.9.12.4 Distributed Action Definition..................................................................... 213

12.9.12.5 Scope in Fact‑set Query Functions............................................................ 214

12.9.12.6 Errors during Instance‑set Query Functions.............................................. 214

12.9.12.7 Halting and Returning Values from Query Functions................................ 215

12.9.12.8 Fact‑set Query Functions........................................................................... 215

12.10 Deffacts Functions....................................................................................................... 218

12.10.1 Getting the List of Deffacts................................................................................. 218

12.10.2 Determining the Module in which a Deffacts is Defined.................................... 219

12.11 Defrule Functions........................................................................................................ 219

12.11.1 Getting the List of Defrules................................................................................. 219

12.11.2 Determining the Module in which a Defrule is Defined...................................... 219

12.12 Agenda Functions........................................................................................................ 219

12.12.1 Getting the Current Focus................................................................................... 220

12.12.2 Getting the Focus Stack...................................................................................... 220

12.12.3 Removing the Current Focus from the Focus Stack............................................ 220

12.13 Defglobal Functions..................................................................................................... 221

12.13.1 Getting the List of Defglobals............................................................................. 221

12.13.2 Determining the Module in which a Defglobal is Defined.................................. 221

12.14 Deffunction Functions................................................................................................. 222

12.14.1 Getting the List of Deffunctions.......................................................................... 222

12.14.2 Determining the Module in which a Deffunction is Defined............................... 222

12.15 Generic Function Functions......................................................................................... 222

12.15.1 Getting the List of Defgenerics........................................................................... 222

12.15.2 Determining the Module in which a Generic Function is Defined...................... 223

12.15.3 Getting the List of Defmethods........................................................................... 223

12.15.4 Type Determination............................................................................................. 223

12.15.5 Existence of Shadowed Methods........................................................................ 224

12.15.6 Calling Shadowed Methods................................................................................ 224

12.15.7 Calling Shadowed Methods with Overrides....................................................... 225

12.15.8 Calling a Specific Method................................................................................... 225

12.15.9 Getting the Restrictions of Defmethods.............................................................. 226

12.16 CLIPS Object-Oriented Language (COOL) Functions................................................ 227

12.16.1 Class Functions................................................................................................... 227

12.16.1.1 Getting the List of Defclasses.................................................................... 227

12.16.1.2 Determining the Module in which a Defclass is Defined........................... 228

12.16.1.3 Determining if a Class Exists..................................................................... 228

12.16.1.4 Superclass Determination........................................................................... 228

12.16.1.5 Subclass Determination.............................................................................. 228

12.16.1.6 Slot Existence............................................................................................. 228

12.16.1.7 Testing whether a Slot is Writable.............................................................. 229

12.16.1.8 Testing whether a Slot is Initializable......................................................... 229

12.16.1.9 Testing whether a Slot is Public................................................................. 229

12.16.1.10 Testing whether a Slot can be Accessed Directly..................................... 229

12.16.1.11 Message‑handler Existence...................................................................... 229

12.16.1.12 Determining if a Class can have Direct Instances..................................... 230

12.16.1.13 Determining if a Class can Satisfy Object Patterns.................................. 230

12.16.1.14 Getting the List of Superclasses for a Class............................................. 230

12.16.1.15 Getting the List of Subclasses for a Class................................................ 230

12.16.1.16 Getting the List of Slots for a Class......................................................... 231

12.16.1.17 Getting the List of Message‑Handlers for a Class.................................... 231

12.16.1.18 Getting the List of Facets for a Slot.......................................................... 232

12.16.1.19 Getting the List of Source Classes for a Slot............................................ 232

12.16.1.20 Getting the Primitive Types for a Slot...................................................... 233

12.16.1.21 Getting the Cardinality for a Slot.............................................................. 233

12.16.1.22 Getting the Allowed Values for a Slot..................................................... 234

12.16.1.23 Getting the Numeric Range for a Slot...................................................... 234

12.16.1.24 Getting the Default Value for a Slot......................................................... 235

12.16.1.25 Setting the Defaults Mode for Classes..................................................... 235

12.16.1.26 Getting the Defaults Mode for Classes.................................................... 236

12.16.1.27 Getting the Allowed Values for a Slot..................................................... 236

12.16.2 Message‑handler Functions................................................................................ 236

12.16.2.1 Existence of Shadowed Handlers............................................................... 236

12.16.2.2 Calling Shadowed Handlers....................................................................... 237

12.16.2.3 Calling Shadowed Handlers with Different Arguments............................. 237

12.16.3 Definstances Functions....................................................................................... 238

12.16.3.1 Getting the List of Definstances................................................................. 238

12.16.3.2 Determining the Module in which a Definstances is Defined.................... 238

12.16.4 Instance Manipulation Functions and Actions.................................................... 239

12.16.4.1 Initializing an Instance................................................................................ 239

12.16.4.2 Deleting an Instance................................................................................... 239

12.16.4.3 Deleting the Active Instance from a Handler.............................................. 239

12.16.4.4 Determining the Class of an Object............................................................ 240

12.16.4.5 Determining the Name of an Instance........................................................ 240

12.16.4.6 Determining the Address of an Instance.................................................... 240

12.16.4.7 Converting a Symbol to an Instance‑Name................................................ 240

12.16.4.8 Converting an Instance‑Name to a Symbol................................................ 241

12.16.4.9 Predicate Functions.................................................................................... 241

12.16.4.10 Reading a Slot Value................................................................................ 242

12.16.4.11 Setting a Slot Value.................................................................................. 242

12.16.4.12 Multifield Slot Functions......................................................................... 242

12.17 Defmodule Functions................................................................................................... 244

12.17.1 Getting the List of Defmodules........................................................................... 244

12.17.2 Setting the Current Module................................................................................. 245

12.17.3 Getting the Current Module................................................................................ 245

12.18 Sequence Expansion.................................................................................................... 245

12.18.1 Sequence Expansion and Rules........................................................................... 246

12.18.2 Multifield Expansion Function............................................................................ 247

12.18.3 Setting The Sequence Operator Recognition Behavior........................................ 247

12.18.4 Getting The Sequence Operator Recognition Behavior....................................... 248

12.18.5 Sequence Operator Caveat.................................................................................. 248

Section 13 ‑ Commands............................................................................................................ 249

13.1 Environment Commands................................................................................................ 249

13.1.1 Loading Constructs From A File.......................................................................... 249

13.1.2 Loading Constructs From A File without Progress Information........................... 249

13.1.3 Saving All Constructs To A File........................................................................... 249

13.1.4 Loading a Binary Image........................................................................................ 250

13.1.5 Saving a Binary Image.......................................................................................... 250

13.1.6 Clearing CLIPS..................................................................................................... 251

13.1.7 Exiting CLIPS....................................................................................................... 251

13.1.8 Resetting CLIPS................................................................................................... 251

13.1.9 Executing Commands From a File........................................................................ 252

13.1.10 Executing Commands From a File Without Replacing Standard Input............... 252

13.1.11 Determining CLIPS Compilation Options.......................................................... 252

13.1.12 Calling the Operating System.............................................................................. 253

13.1.13 Setting The Auto‑Float Dividend Behavior......................................................... 253

13.1.14 Getting The Auto‑Float Dividend Behavior........................................................ 253

13.1.15 Setting the Dynamic Constraint Checking Behavior........................................... 254

13.1.16 Getting the Dynamic Constraint Checking Behavior........................................... 254

13.1.17 Setting the Static Constraint Checking Behavior................................................. 254

13.1.18 Getting the Static Constraint Checking Behavior................................................ 254

13.1.19 Finding Symbols................................................................................................. 254

13.2 Debugging Commands.................................................................................................. 255

13.2.1 Generating Trace Files.......................................................................................... 255

13.2.2 Closing Trace Files............................................................................................... 255

13.2.3 Enabling Watch Items........................................................................................... 255

13.2.4 Disabling Watch Items.......................................................................................... 257

13.2.5 Viewing the Current State of Watch Items............................................................ 257

13.3 Deftemplate Commands................................................................................................. 258

13.3.1 Displaying the Text of a Deftemplate.................................................................... 258

13.3.2 Displaying the List of Deftemplates...................................................................... 258

13.3.3 Deleting a Deftemplate.......................................................................................... 259

13.4 Fact Commands............................................................................................................. 259

13.4.1 Displaying the Fact-List........................................................................................ 259

13.4.2 Loading Facts From a File.................................................................................... 259

13.4.3 Saving The Fact-List To A File............................................................................. 260

13.4.4 Setting the Duplication Behavior of Facts............................................................. 260

13.4.5 Getting the Duplication Behavior of Facts............................................................ 261

13.4.6 Displaying a Single Fact....................................................................................... 261

13.5 Deffacts Commands....................................................................................................... 262

13.5.1 Displaying the Text of a Deffacts.......................................................................... 262

13.5.2 Displaying the List of Deffacts............................................................................. 262

13.5.3 Deleting a Deffacts................................................................................................ 262

13.6 Defrule Commands........................................................................................................ 263

13.6.1 Displaying the Text of a Rule................................................................................ 263

13.6.2 Displaying the List of Rules.................................................................................. 263

13.6.3 Deleting a Defrule................................................................................................. 263

13.6.4 Displaying Matches for a Rule.............................................................................. 263

13.6.5 Setting a Breakpoint for a Rule............................................................................. 265

13.6.6 Removing a Breakpoint for a Rule........................................................................ 266

13.6.7 Displaying Rule Breakpoints................................................................................ 266

13.6.8 Refreshing a Rule.................................................................................................. 266

13.6.9 Setting the Incremental Reset Behavior................................................................. 266

13.6.10 Getting the Incremental Reset Behavior.............................................................. 267

13.6.11 Determining the Logical Dependencies of a Pattern Entity.................................. 267

13.6.12 Determining the Logical Dependents of a Pattern Entity..................................... 267

13.7 Agenda Commands........................................................................................................ 268

13.7.1 Displaying the Agenda.......................................................................................... 268

13.7.2 Running CLIPS.................................................................................................... 268

13.7.3 Focusing on a Group of Rules.............................................................................. 268

13.7.4 Stopping Rule Execution....................................................................................... 269

13.7.5 Setting The Current Conflict Resolution Strategy................................................. 269

13.7.6 Getting The Current Conflict Resolution Strategy................................................. 269

13.7.7 Listing the Module Names on the Focus Stack..................................................... 269

13.7.8 Removing all Module Names from the Focus Stack............................................. 270

13.7.9 Setting the Salience Evaluation Behavior.............................................................. 270

13.7.10 Getting the Salience Evaluation Behavior............................................................ 270

13.7.11 Refreshing the Salience Value of Rules on the Agenda...................................... 270

13.8 Defglobal Commands.................................................................................................... 271

13.8.1 Displaying the Text of a Defglobal....................................................................... 271

13.8.2 Displaying the List of Defglobals......................................................................... 271

13.8.3 Deleting a Defglobal............................................................................................. 271

13.8.4 Displaying the Values of Global Variables........................................................... 271

13.8.5 Setting the Reset Behavior of Global Variables.................................................... 272

13.8.6 Getting the Reset Behavior of Global Variables.................................................... 272

13.9 Deffunction Commands................................................................................................. 272

13.9.1 Displaying the Text of a Deffunction.................................................................... 272

13.9.2 Displaying the List of Deffunctions...................................................................... 272

13.9.3 Deleting a Deffunction.......................................................................................... 273

13.10 Generic Function Commands....................................................................................... 273

13.10.1 Displaying the Text of a Generic Function Header............................................. 273

13.10.2 Displaying the Text of a Generic Function Method............................................ 273

13.10.3 Displaying the List of Generic Functions............................................................ 273

13.10.4 Displaying the List of Methods for a Generic Function...................................... 274

13.10.5 Deleting a Generic Function................................................................................ 274

13.10.6 Deleting a Generic Function Method.................................................................. 274

13.10.7 Previewing a Generic Function Call.................................................................... 275

13.11 CLIPS Object‑Oriented Language (COOL) Commands.............................................. 275

13.11.1 Class Commands................................................................................................ 275

13.11.1.1 Displaying the Text of a Defclass.............................................................. 275

13.11.1.2 Displaying the List of Defclasses............................................................... 276

13.11.1.3 Deleting a Defclass.................................................................................... 276

13.11.1.4 Examining a Class...................................................................................... 276

13.11.1.5 Examining the Class Hierarchy.................................................................. 278

13.11.2 Message‑handler Commands.............................................................................. 279

13.11.2.1 Displaying the Text of a Defmessage‑handler............................................ 279

13.11.2.2 Displaying the List of Defmessage‑handlers.............................................. 279

13.11.2.3 Deleting a Defmessage‑handler.................................................................. 280

13.11.2.4 Previewing a Message............................................................................... 280

13.11.3 Definstances Commands..................................................................................... 281

13.11.3.1 Displaying the Text of a Definstances........................................................ 281

13.11.3.2 Displaying the List of Definstances........................................................... 281

13.11.3.3 Deleting a Definstances.............................................................................. 282

13.11.4 Instances Commands.......................................................................................... 282

13.11.4.1 Listing the Instances................................................................................... 282

13.11.4.2 Printing an Instance’s Slots from a Handler............................................... 283

13.11.4.3 Saving Instances to a Text File................................................................... 283

13.11.4.4 Saving Instances to a Binary File............................................................... 284

13.11.4.5 Loading Instances from a Text File............................................................ 284

13.11.4.6 Loading Instances from a Text File without Message Passing................... 284

13.11.4.7 Loading Instances from a Binary File........................................................ 284

13.12 Defmodule Commands................................................................................................ 285

13.12.1 Displaying the Text of a Defmodule................................................................... 285

13.12.2 Displaying the List of Defmodules..................................................................... 285

13.13 Memory Management Commands............................................................................... 285

13.13.1 Determining the Amount of Memory Used by CLIPS....................................... 285

13.13.2 Determining the Number of Memory Requests Made by CLIPS....................... 285

13.13.3 Releasing Memory Used by CLIPS.................................................................... 286

13.13.4 Conserving Memory........................................................................................... 286

13.14 On‑Line Help System.................................................................................................. 286

13.14.1 Using the CLIPS Help Facility........................................................................... 286

13.14.2 Finding the Help File.......................................................................................... 287

13.15 External Text Manipulation.......................................................................................... 288

13.15.1 External Text File Format.................................................................................... 288

13.15.2 External Text Manipulation Functions................................................................ 290

13.15.2.1 Fetch.......................................................................................................... 290

13.15.2.2 Print‑region................................................................................................ 290

13.15.2.3 Get‑region.................................................................................................. 292

13.15.2.4 Toss........................................................................................................... 292

13.16 Profiling Commands.................................................................................................... 292

13.16.1 Setting the Profiling Report Threshold................................................................ 292

13.16.2 Getting the Profiling Report Threshold............................................................... 293

13.16.3 Resetting Profiling Information........................................................................... 293

13.16.4 Displaying Profiling Information........................................................................ 293

13.16.5 Profiling Constructs and User Functions............................................................ 293

Appendix A ‑ Support Information........................................................................................ 297

A.1 Questions and Information.............................................................................................. 297

A.2 Documentation................................................................................................................ 297

A.3 CLIPS Source Code and Executables............................................................................. 297

Appendix B ‑ Update Release Notes........................................................................................ 299

B.1 Version 6.30.................................................................................................................... 299

B.2 Version 6.24.................................................................................................................... 300

B.3 Version 6.23.................................................................................................................... 302

B.4 Version 6.22.................................................................................................................... 303

B.5 Version 6.21.................................................................................................................... 303

B.6 Version 6.2...................................................................................................................... 304

B.7 Version 6.1...................................................................................................................... 306

B.8 Version 6.05.................................................................................................................... 307

B.9 Version 6.04.................................................................................................................... 310

B.10 Version 6.03.................................................................................................................. 311

B.11 Version 6.02.................................................................................................................. 312

B.12 Version 6.01.................................................................................................................. 313

Appendix C ‑ Glossary.............................................................................................................. 315

Appendix D ‑ Integrated Editor............................................................................................... 323

D.1 Special characters............................................................................................................ 323

D.2 Control Commands......................................................................................................... 324

D.3 Extended (Control‑X) Commands.................................................................................. 325

D.4 Meta Commands  (Activated by <esc> or <ctrl‑[>)........................................................ 326

Appendix E ‑ Performance Considerations............................................................................ 327

E.1 Ordering of Patterns on the LHS..................................................................................... 327

E.2 Deffunctions versus Generic Functions........................................................................... 328

E.3 Ordering of Method Parameter Restrictions.................................................................... 329

E.4 Instance‑Addresses versus Instance‑Names.................................................................... 329

E.5 Reading Instance Slots Directly....................................................................................... 329

Appendix F ‑ CLIPS Warning Messages................................................................................ 331

Appendix G ‑ CLIPS Error Messages..................................................................................... 333

Appendix H ‑ CLIPS BNF........................................................................................................ 371

Appendix I ‑ Reserved Function Names................................................................................. 379

Appendix J ‑ Bibliography of CLIPS Publications................................................................ 385

Index........................................................................................................................................... 393


License Information

 

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so.

 

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

 

CLIPS is released as public domain software and as such you are under no obligation to pay for its use. However, if you derive commercial or monetary benefit from use of the software or just want to show support, please consider making a voluntary payment based on the worth of the software to you as compensation for the time and effort required to develop and maintain CLIPS. Payments can be made online at http://order.kagi.com/?JKT.


Preface

 

The History of CLIPS

 

The origins of the C Language Integrated Production System (CLIPS) date back to 1984 at NASA’s Johnson Space Center. At this time, the Artificial Intelligence Section had developed over a dozen prototype expert systems applications using state‑of‑the‑art hardware and software. However, despite extensive demonstrations of the potential of expert systems, few of these applications were put into regular use. This failure to provide expert systems technology within NASA’s operational computing constraints could largely be traced to the use of LISP as the base language for nearly all expert system software tools at that time. In particular, three problems hindered the use of LISP based expert system tools within NASA: the low availability of LISP on a wide variety of conventional computers, the high cost of state‑of‑the‑art LISP tools and hardware, and the poor integra­tion of LISP with other languages (making embedded applications difficult).

 

The Artificial Intelligence Section felt that the use of a conventional language, such as C, would eliminate most of these problems, and initially looked to the expert system tool vendors to provide an expert system tool written using a conventional language. Although a number of tool vendors started converting their tools to run in C, the cost of each tool was still very high, most were restricted to a small variety of computers, and the projected availability times were discouraging. To meet all of its needs in a timely and cost effective manner, it became evident that the Artificial Intelligence Section would have to develop its own C based expert system tool.

 

The prototype version of CLIPS was developed in the spring of 1985 in a little over two months. Particular attention was given to making the tool compatible with expert systems under development at that time by the Artificial Intelligence Section. Thus, the syntax of CLIPS was made to very closely resemble the syntax of a subset of the ART expert system tool developed by Inference Corporation. Although originally modelled from ART, CLIPS was developed entirely without assistance from Inference or access to the ART source code.

 

The original intent for CLIPS was to gain useful insight and knowledge about the construction of expert system tools and to lay the groundwork for the construction of a replacement tool for the commercial tools currently being used. Version 1.0 demonstrated the feasibility of the project concept. After additional development, it became apparent that CLIPS would be a low cost expert system tool ideal for the purposes of training. Another year of development and internal use went into CLIPS improving its portability, performance, functionality, and supporting documentation. Version 3.0 of CLIPS was made available to groups outside of NASA in the summer of 1986.

 

Further enhancements transformed CLIPS from a training tool into a tool useful for the development and delivery of expert systems as well. Versions 4.0 and 4.1 of CLIPS, released respectively in the summer and fall of 1987, featured greatly improved performance, external language integration, and delivery capabilities. Version 4.2 of CLIPS, released in the summer of 1988, was a complete rewrite of CLIPS for code modularity. Also included with this release were an architecture manual providing a detailed description of the CLIPS software architecture and a utility program for aiding in the verification and validation of rule‑based programs. Version 4.3 of CLIPS, released in the summer of 1989, added still more functionality.

 

Originally, the primary representation methodology in CLIPS was a forward chaining rule lan­guage based on the Rete algorithm (hence the Production System part of the CLIPS acronym). Version 5.0 of CLIPS, released in the spring of 1991, introduced two new programming paradigms: procedural programming (as found in languages such as C and Ada) and object‑oriented programming (as found in languages such as the Common Lisp Object System and Smalltalk). The object‑oriented programming language provided within CLIPS is called the CLIPS Object‑Oriented Language (COOL). Version 5.1 of CLIPS, released in the fall of 1991, was primarily a software maintenance upgrade required to support the newly developed and/or enhanced X Window, MS‑DOS, and Macintosh interfaces. Version 6.0 of CLIPS, released in 1993, provided support for the development of modular programs and tight integration between the object-oriented and rule-based programming capabilities of CLIPS. Version 6.1 of CLIPS, released in 1998, removed support for older non-ANSI C Compilers and added support for C++ compilers. Commands to profile the time spent in constructs and user-defined functions were also added. Version 6.2 of CLIPS, released in 2002, added support for multiple environments into which programs can be loaded and improved Windows XP and MacOS development interfaces.

 

Because of its portability, extensibility, capabilities, and low cost, CLIPS has received widespread acceptance throughout the government, industry, and academia. The development of CLIPS has helped to improve the ability to deliver expert system technology throughout the public and private sectors for a wide range of applications and diverse computing environments. CLIPS is being used by numerous users throughout the public and private community including: all NASA sites and branches of the mil­itary, numerous federal bureaus, gov­ernment contractors, uni­versities, and many private compa­nies.

 

CLIPS is now maintained as public domain software by the main program authors who no longer work for NASA. See appendix A of the Basic Programming Guide for information on obtaining CLIPS and support.

 

CLIPS Version 6.3

 

Version 6.3 of CLIPS contains two major enhancements. First, rule performance has been improved particularly in situations with large numbers of facts/instances or partial matches. Second, support for integration with languages such as Java and C++ has been improved. For a detailed listing of differences between the 6.x releases of CLIPS, refer to appendix B of the Basic Programming Guide and appendix C of the Advanced Programming Guide.


CLIPS Documentation

 

Two documents are provided with CLIPS.

 

     The CLIPS Reference Manual which is split into the following parts:

 

     Volume I - The Basic Programming Guide, which provides the definitive description of CLIPS syntax and examples of usage.

 

     Volume II - The Advanced Programming Guide, which provides detailed discus­sions of the more sophisticated features in CLIPS and is intended for people with extensive programming experience who are using CLIPS for advanced ap­plications.

 

     Volume III - The Interfaces Guide, which provides information on machine‑specific interfaces.

 

     The CLIPS User’s Guide which provides an introduction to CLIPS rule‑based and object‑oriented programming and is intended for people with little or no expert system experience.

 

 


Acknowledgements

As 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 Dantes, 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.

 

Many other individuals contributed to the design, development, review, and general support of CLIPS, including: Jack Aldridge, Carla Colangelo, Paul Baffes, Ann Baker, Stephen Baudendistel, Les Berke, Tom Blinn, Marlon Boarnet, Dan Bochsler, Bob Brown, Barry Cameron, Tim Cleghorn, Major Paul Condit, Major Steve Cross, Andy Cunningham, Dan Danley, Mark Engelberg, Kirt Fields, Ken Freeman, Kevin Greiner, Ervin Grice, Sharon Hecht, Patti Herrick, Mark Hoffman, Grace Hua, Gordon Johnson, Phillip Johnston, Sam Juliano, Ed Lineberry, Bowen Loftin, Linda Martin, Daniel McCoy, Terry McGregor, Becky McGuire, Scott Meadows, C. J. Melebeck, Paul Mitchell, Steve Mueller, Bill Paseman, Cynthia Rathjen, Eric Raymond, Reza Razavipour, Marsha Renals, Monica Rua, Tim Saito, Michael Sullivan, Gregg Swietek, Eric Taylor, James Villarreal, Lui Wang, Bob Way, Jim Wescott, Charlie Wheeler, and Wes White.


Section 1 ‑ Introduction

This 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, al­though 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.

 

The Basic Programming Guide documents just the basic CLIPS syntax. More advanced capabilities, such as user‑defined functions, embedded applications, etc., are docu­mented more fully in the Advanced Programming Guide. The Advanced Programming Guide is intended for users who have a complete knowledge of the CLIPS syntax and a programming background. It is not  necessary to read the Advanced Program­ming Guide to learn how to use CLIPS. CLIPS can be learned and simple expert systems can be built with the information provided in this manual.


Section 2 ‑ CLIPS Overview

This section gives a general overview of CLIPS and of the basic concepts used through­out this manual.

2.1 Interacting with CLIPS

CLIPS 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 ma­chines; or as embedded expert systems in which the user provides a main pro­gram and controls execution of the expert system. Embedded applications are dis­cussed in the Advanced Programming Guide. In addition, a series of commands can be automatically read di­rectly from a file when CLIPS is first started or as the result of the batch command.

 

The generic CLIPS interface is a simple, interactive, text‑oriented, command prompt interface for high porta­bility. The stan­dard usage is to create or edit a knowledge base using any standard text editor, save the knowledge base as one or more text files, exit the editor and execute CLIPS, then load the knowledge base into CLIPS. The in­terface provides commands for viewing the current state of the sys­tem, tracing execu­tion, adding or removing information, and clearing CLIPS.

 

A more sophisticated window interface is available for the Macintosh, Windows 3.1, and X Window environments. All interface commands described in this section are available in the window interfaces. These interfaces are described in more detail in the Interfaces Guide.

2.1.1 Top Level Commands

The 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, local or 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. Local variables can be set at the command prompt using the bind function and retain their value until a reset or clear command is issued. Entering a local variable at the command prompt causes the value of the local 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 (V6.3 10/25/07)

CLIPS> (+ 3 4)

7

CLIPS> (defglobal ?*x* = 3)

CLIPS> ?*x*

3

CLIPS> red

red

CLIPS> (bind ?a 5)

5

CLIPS> (+ ?a 3)

8

CLIPS> (reset)

CLIPS> ?a

[EVALUATN1] Variable a is unbound

FALSE

CLIPS>

 

The previous example first called the addition function adding the numbers 3 and 4 to yield the result 7. A global variable ?*x* was then defined and given the value 3. The variable ?*x* was then entered at the prompt and its value of 3 was returned. Finally the constant symbol red was entered and was returned (since a constant evaluates to itself).

2.1.2 Automated Command Entry and Loading

Some 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>*

 

<option> ::= -f <filename> |

             -f2 <filename> |

             -l <filename>

 

For the ‑f option, <filename> is a file that contains CLIPS commands. If the exit command is included in the file, CLIPS will halt and the user is returned to the operat­ing system after executing the commands in the file. If an exit command is not in the file, CLIPS will enter in its interactive state after executing the commands in the file. Commands in the file should be entered exactly as they would be interactively (i.e. opening and closing parentheses must be included and a carriage return must be at the end of the command). The ‑f command line option is equivalent to interactively entering a batch command as the first command to the CLIPS prompt.

 

The -f2 option is similar to the -f option, but is equivalent to interactively entering a batch* command. The commands stored in <filename> are immediately executed, but the commands and their return values are not displayed as they would be for a batch command.

 

For the -l option, <filename> should be a file containing CLIPS constructs. This file will be loaded into the environment. The ‑l command line option is equivalent to interactively entering a load command.

2.1.3 Integration with Other Languages

When 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.

 

Using CLIPS as an embedded application allows the easy integration of CLIPS with existing systems. This is useful in cases where the expert system is a small part of a larger task or needs to share data with other functions. In these situations, CLIPS can be called as a subroutine and information may be passed to and from CLIPS. Em­bedded applications are discussed in the Advanced Programming Guide.

 

It also may be useful to call external functions while executing a CLIPS construct or from the top‑level of the interactive interface. CLIPS variables or literal values may be passed to an external function, and functions may return val­ues to CLIPS. The easy addition of external functions allows CLIPS to be extended or customized in almost any way. The Advanced Programming Guide describes how to integrate CLIPS with functions or systems written in C as well as in other lan­guages.

2.2 Reference Manual Syntax

The terminology used throughout this manual to describe the CLIPS syntax is fairly com­mon to computer reference manuals. Plain words or characters, particularly paren­theses, 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 re­turns) 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>.

 

<lexeme> ::= <symbol> | <string>

 

A complete BNF listing for CLIPS constructs along with some commonly used replacements for non‑terminal symbols are listed in appendix I.

2.3 Basic Programming Elements

CLIPS 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 Types

CLIPS 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.

 

A .ib;number; consists only of digits (0‑9), a decimal point (.), a sign (+ or ‑), and, optionally, an (e) for exponential notation with its corresponding sign. A number is either stored as a float; or an integer. Any number consisting of an optional sign followed by only digits is stored as an integer (represented internally by CLIPS as a C long integer). All other numbers are stored as floats (represented internally by CLIPS as a C double‑precision float). The number of significant digits will de­pend on the machine implementation. Roundoff errors also may occur, again depend­ing on the machine implementation. As with any computer language, care should be taken when comparing floating‑point values to each other or comparing integers to floating‑point values. Some examples of integers are

 

237           15             +12            -32

 

Some examples of floats are

 

237e3         15.09          +12.0          -32.3e-7

 

Specifically, integers use the following format:

 

<integer> ::= [+ | -] <digit>+

 

<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

 

Floating point numbers use the following format:

 

<float> ::= <integer> <exponent> |

 

            <integer> . [exponent]

 

            . <unsigned integer> [exponent]

 

            <integer> . <unsigned integer> [exponent]

 

<unsigned-integer> ::= <digit>+

 

<exponent> ::= e | E <integer>

 

A sequence of characters which does not exactly follow the format of a number is treated as a symbol (see the next paragraph).

 

A symbol in CLIPS is any sequence of characters that starts with any printable ASCII character and is followed by zero or more printable ASCII characters. When a delimiter is found, the symbol is ended. The following characters act as delimiters: any non‑printable ASCII character (including spaces, tabs, carriage returns, and line feeds), a double quote, opening and closing parentheses “(” and “)”, an ampersand “&”, a vertical bar “|”, a less than “<”, and a tilde “~”. A semicolon “;” starts a CLIPS comment (see section 2.3.3) and also acts as a de­limiter. Delimiters may not be included in symbols with the exception of the “<“ character which may be the first character in a symbol. In addition, a symbol may not begin with either the “?” character or the “$?” sequence of characters (although a symbol may contain these characters). These characters are reserved for variables (which are discussed later in this section). CLIPS is case sensitive (i.e. uppercase letters will match only uppercase let­ters). Note that numbers are a special case of symbols (i.e. they satisfy the definition of a symbol, but they are treated as a different data type). Some simple examples of symbols are

 

foo           Hello          B76-HI         bad_value

 

127A          456-93-039     @+=-%          2each

 

A string is a set of characters that starts with a double quote (") and is followed by zero or more printable characters. A string ends with double quotes. Double quotes may be embedded within a string by placing a backslash (\) in front of the character. A backslash may be embedded by placing two consecutive back­slash characters in the string. Some examples are

 

"foo"         "a and b"      "1 number"     "a\"quote"

 

Note that the string “abcd" is not the same as the symbol abcd. They both contain the same characters, but are of different types. The same holds true for the instance name [abcd].

 

An external‑address is the address of an external data structure returned by a function (written in a language such as C or Ada) that has been integrated with CLIPS. This data type can only be created by calling a function (i.e. it is not possible to specify an external‑address by typing the value). In the basic version of CLIPS (which has no user defined external functions), it is not possible to create this data type. External‑addresses are discussed in further detail in the Advanced Programming Guide;. Within CLIPS, the printed representation of an external‑address is

 

<Pointer-XXXXXX>

 

where XXXXXX is the external‑address.

 

A fact is a list of atomic values that are either referenced positionally (ordered facts) or by name (non‑ordered or template facts). Facts are referred to by index or address; section 2.4.1 gives more details. The printed format of a fact‑address is:

 

<Fact-XXX>

 

where XXX is the fact‑index.

 

An instance is an object that is an instantiation or specific example of a class. Objects in CLIPS are defined to be floats, integers, symbols, strings, multifield values, external‑addresses, fact‑addresses or instances of a user‑defined class. A user‑defined class is created using the defclass construct. An instance of a user‑defined class is created with the make‑instance function, and such an instance can be referred to uniquely by address. Within the scope of a module (see section 10.5.1), an instance can also be uniquely referred to by name. All of these definitions will be covered in more detail in Sections 2.4.2, 2.5.2.3, 2.6 and 9. An instance‑name is formed by enclosing a symbol within left and right brackets. Thus, pure symbols may not be surrounded by brackets. If the CLIPS Object Oriented Language (COOL) is not included in a particular CLIPS configuration, then brackets may be wrapped around symbols. Some examples of instance‑names are:

 

[pump-1]      [foo]          [+++]          [123-890]

 

Note that the brackets are not part of the name of the instance; they merely indicate that the enclosed symbol is an instance‑name. An instance‑address can only be obtained by binding the return value of a function called instance‑address or by binding a variable to an instance matching an object pattern on the LHS of a rule (i.e., it is not possible to specify an instance‑address by typing the value). A reference to an instance of a user‑defined class can either be by name or address; instance‑addresses should only be used when speed is critical. Within CLIPS, the printed representation of an instance‑address is

 

<Instance-XXX>

 

where XXX is the name of the instance.

 

In CLIPS, a placeholder that has a value (one of the primitive data types) is referred to as a field. The primitive data types are referred to as single‑field values. A constant is a non‑varying single field value directly expressed as a series of characters (which means that external‑addresses, fact‑addresses and instance‑addresses cannot be expressed as constants because they can only be obtained through function calls and variable bindings). A multifield value is a sequence of zero or more single field values. When displayed by CLIPS, multifield values are enclosed in parentheses. Collectively, single and multifield values are referred to as values. Some examples of multifield values are

 

(a)           (1 bar foo)    ()             (x 3.0 "red" 567)

 

Note that the multifield value (a) is not the same as the single field value a. Multifield values are created either by calling functions which return multifield values, by using wildcard arguments in a deffunction, object message‑handler, or method, or by binding variables during the pattern‑matching process for rules. In CLIPS, a variable is a symbolic location that is used to store values. Variables are used by many of the CLIPS constructs (such as defrule, deffunction, defmethod, and defmessage‑handler) and their usage is explained in the sections describing each of these constructs.

2.3.2 Functions

A 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).

 

There are several types of functions. User defined functions and system defined functions are pieces of code that have been written in an external language (such as C, FORTRAN, or Ada) and linked with the CLIPS environment. System defined functions are those functions that have been defined internally by the CLIPS environment. User defined functions are functions that have been defined externally of the CLIPS environment. A complete list of system defined functions can be found in appendix J.

 

The deffunction construct allows users to define new functions directly in the CLIPS environment using CLIPS syntax. Functions defined in this manner appear and act like other functions, however, instead of being directly executed (as code written in an external language would be) they are interpreted by the CLIPS environment. Deffunctions are also discussed in section 2.5.2.1 in the context of procedural knowledge representation.

 

Generic functions can be defined using the defgeneric and defmethod constructs. Generic functions allow different pieces of code to be executed depending upon the arguments passed to the generic function. Thus, a single function name can be overloaded with more than one piece of code. Generic functions are also discussed in section 2.5.2.2 in the context of procedural knowledge representation.

 

Function calls in CLIPS use a prefix notation – the arguments to a function always appear after the function name. Function calls begin with a left parenthesis, followed by the name of the function, then the arguments to the function follow (each argument separated by one or more spaces). Arguments to a function can be primitive data types, variables, or another function call. The function call is then closed with a right parenthesis. Some examples of function calls using the addition (+) and multiplication (*) functions are shown following.

 

(+ 3 4 5)

(* 5 6.0 2)

(+ 3 (* 8 9) 4)

(* 8 (+ 3 (* 2 3 4) 9) (* 3 4))

 

While a function refers to a piece of executable code identified by a specific name,  an expression refers to a function which has its arguments specified (which may or may not be functions calls as well). Thus the previous examples are expressions which make calls to the * and + functions.

2.3.3 Constructs

Several 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 parenthe­sis 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.

 

As with any programming language, it is highly beneficial to comment CLIPS code. All constructs (with the exception of defglobal) allow a comment directly following the construct name. Comments also can be placed within CLIPS code by using a semicolon (;). Everything from the semicolon until the next return character will be ignored by CLIPS. If the semicolon is the first character in the line, the entire line will be treated as a comment. Examples of commented code will be pro­vided throughout the reference manual. Semicolon commented text is not saved by CLIPS when loading constructs (however, the optional comment string within a construct is saved).

2.4 Data Abstraction

There are three primary formats for representing information in CLIPS: facts, objects and global variables.

2.4.1 Facts

Facts 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).

 

Facts may be added to the fact‑list (using the assert command), removed from the fact‑list (using the retract command), modified (using the modify command), or duplicated (using the duplicate command) through explicit user interaction or as a CLIPS program executes;. The number of facts in the fact‑list  and the amount of information that can be stored in a fact is limited only by the amount of memory in the computer. If a fact is asserted into the fact‑list that exactly matches an already existing fact, the new assertion will be ignored (however, this behavior can be changed, see sections 13.4.4 and 13.4.5).

 

Some commands, such as the retract, modify, and duplicate commands, require a fact to be specified. A fact can be specified either by fact‑index or fact‑address. Whenever a fact is added (or modified) it is given a unique integer index called a fact‑index. Fact‑indices start at zero and are incremented by one for each new or changed fact. Whenever a reset or clear command is given, the fact‑indices restart at zero. A fact may also be specified through the use of a fact‑address. A fact‑address can be obtained by capturing the return value of commands which return fact addresses (such as assert, modify, and duplicate) or by binding a variable to the fact address of a  fact which matches a pattern on the LHS of a rule (see section 5.4.1.8 for details).

 

A fact identifier is a shorthand notation for displaying a fact. It consists of the character “f”, followed by a dash, followed by the fact‑index of the fact. For example, f‑10 refers to the fact with fact‑index 10.

 

A fact is stored in one of two formats: ordered or non‑ordered.

2.4.1.1 Ordered Facts

Ordered 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.

 

Some examples of ordered facts are shown following.

 

(the pump is on)

(altitude is 10000 feet)

(grocery-list bread milk eggs)

 

Fields in a non‑ordered fact may be of any of the primitive data types (with the exception of the first field which must be a symbol), and no restriction is placed on the ordering of fields. The following symbols are reserved and should not be used as the first field in any fact (ordered or non‑ordered): test, and, or, not, declare, logical, object, exists, and forall. These words are reserved only when used as a deftemplate name (whether explicitly defined or implied). These symbols may be used as slot names, however, this is not recommended.

2.4.1.2 Non‑ordered Facts

Ordered 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 assign­ing 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.

 

The deftemplate construct allows the name of a template to be defined along with zero or more definitions of named fields or slots. Unlike ordered facts, the slots of a deftemplate fact may be constrained by type, value, and numeric range. In addition, default values can be specified for a slot. A slot consists of an opening parenthesis followed by the name of the slot, zero or more fields, and a closing parenthesis. Note that slots may not be used in an ordered fact and that positional fields may not be used in a deftemplate fact.

 

Deftemplate facts are distinguished from ordered facts by the first field within the fact. The first field of all facts must be a symbol, however, if that symbol corresponds to the name of a deftemplate, then the fact is a deftemplate fact. The first field of a deftemplate fact is followed by a list of zero or more slots. As with ordered facts, deftemplate facts are enclosed by an opening parenthesis on the left and a closing parenthesis on the right.

 

Some examples of deftemplate facts are shown following.

 

(client (name "Joe Brown") (id X9345A))

(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))

 

Note that the order of slots in a deftemplate fact is not important. For example the following facts are all identical:

 

(class (teacher "Martha Jones") (#-students 30) (Room "37A"))

(class (#-students 30) (teacher "Martha Jones") (Room "37A"))

(class (Room "37A") (#-students 30) (teacher "Martha Jones"))

 

In contrast, note that the following ordered fact are not identical.

 

(class "Martha Jones" 30 "37A")

(class 30 "Martha Jones" "37A")

(class "37A" 30 "Martha Jones")

 

The im­mediate advantages of clarity and slot order independence for deftemplate facts should be readily apparent.

 

In addition to being asserted and retracted, deftemplate facts can also be modified and duplicated (using the modify and duplicate commands). Modifying a fact changes a set of specified slots within that fact. Duplicating a fact creates a new fact identical to the original fact and then changes a set of specified slots within the new fact. The benefit of using the modify and duplicate commands is that slots which don’t change, don’t have to be specified.

2.4.1.3 Initial Facts

The 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 Objects

An 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 class is a template for common properties and behavior of objects which are instances of that class. Some examples of objects and their classes are:

 

Object (Printed Representation)

Class

Rolls‑Royce

SYMBOL

"Rolls‑Royce"

STRING

8.0

FLOAT

8

INTEGER

(8.0 Rolls‑Royce 8 [Rolls‑Royce])

MULTIFIELD

<Pointer- 00CF61AB>

EXTERNAL‑ADDRESS

[Rolls‑Royce]

CAR (a user‑defined class)

 

Objects in CLIPS are split into two important categories: primitive types and instances of user‑defined classes. These two types of objects differ in the way they are referenced, created and deleted as well as how their properties are specified.

 

Primitive type objects are referenced simply by giving their value, and they are created and deleted implicitly by CLIPS as they are needed. Primitive type objects have no names or slots, and their classes are predefined by CLIPS. The behavior of primitive type objects is like that of instances of user‑defined classes, however, in that you can define message‑handlers and attach them to the primitive type classes. It is anticipated that primitive types will not be used often in an object‑oriented programming (OOP) context; the main reason classes are provided for them is for use in generic functions. Generic functions use the classes of their arguments to determine which methods to execute; sections 2.3.2, 2.5.2.2 and 8 give more detail.

 

An instance of a user‑defined class is referenced by name or address, and they are created and deleted explicitly via messages and special functions. The properties of an instance of a user‑defined class are expressed by a set of slots, which the object obtains from its class. As previously defined, slots are named single field or multifield values. For example, the object Rolls‑Royce is an instance of the class CAR. One of the slots in class CAR might be “price”, and the Rolls‑Royce object’s value for this slot might be $75,000.00. The behavior of an object is specified in terms of procedural code called message‑handlers, which are attached to the object’s class. Message‑handlers and manipulation of objects are described in Section 2.5.2.3. All instances of a user‑defined class have the same set of slots, but each instance may have different values for those slots. However, two instances which have the same set of slots do not necessarily belong to the same class, since two different classes can have identical sets of slots.

 

The primary difference between object slots and template (or non‑ordered) facts is the notion of inheritance. Inheritance allows the properties and behavior of a class to be described in terms of other classes. COOL supports multiple inheritance: a class may directly inherit slots and message‑handlers from more than one class. Since inheritance is only useful for slots and message‑handlers, it is often not meaningful to inherit from one of the primitive type classes, such as MULTIFIELD or NUMBER. This is because these classes cannot have slots and usually do not have message‑handlers.

 

Further discussion on these topics can be found in Section 2.6, and a comprehensive description of the CLIPS Object‑Oriented Language (COOL) can be found in Section 9.

2.4.2.1 Initial Objects

The 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 Variables

The 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 Representation

CLIPS 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 – Rules

One 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 de­veloper 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.

 

The antecedent of a rule is a set of conditions (or conditional elements) which must be satisfied for the rule to be applicable. In CLIPS, the conditions of a rule are satisfied based on the existence or non‑existence of specified facts in the fact‑list or specified instances of user‑defined classes in the instance‑list. One type of condition which can be specified is a pattern. Patterns consist of a set of restrictions which are used to determine which facts or objects satisfy the condition specified by the pattern. The process of matching facts and objects to patterns is called pattern‑matching. CLIPS provides a mechanism, called the inference engine, which automatically matches patterns against the current state of the fact‑list and instance‑list and determines which rules are applicable.

 

The consequent of a rule is the set of actions to be executed when the rule is applicable. The actions of applicable rules are executed when the CLIPS inference engine is instructed to begin execution of applicable rules. If more than one rule is applicable, the inference engine uses a conflict resolution strategy to select which rule should have its actions executed. The actions of the selected rule are executed (which may affect the list of applicable rules) and then the inference engine selects another rule and executes its actions. This process continues until no applicable rules remain.

 

In many ways, rules can be thought of as IF‑THEN statements found in procedural programming languages such as C and Ada. However, the conditions of an IF‑THEN statement in a procedural language are only evaluated when the program flow of control is directly at the IF‑THEN statement. In contrast, rules act like WHENEVER‑THEN statements. The inference engine always keeps track of rules which have their conditions satisfied and thus rules can immediately be executed when they are applicable. In this sense, rules are similar to exception handlers found in languages such as Ada.

2.5.2 Procedural Knowledge

CLIPS 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 Deffunctions

Deffunctions 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 Functions

Generic 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‑Passing

Objects 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.

 

Further discussion on message‑handlers can be found in Section 2.6, and a comprehensive description of the CLIPS Object‑Oriented Language (COOL) can be found in Section 9.

2.5.2.4 Defmodules

Defmodules 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 Language

This 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 Paradigm

In 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.

 

All programming elements which are not objects must be manipulated in a non‑OOP utilizing function tailored for those programming elements. For example, to print a rule, you call the function ppdefrule; you do not send a message “print” to a rule, since it is not an object.

2.6.2 Primary OOP Features

There 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.

 

The definitions of new classes allows the abstraction of new data types in COOL. The slots and message‑handlers of these classes describe the properties and behavior of a new group of objects.

 

COOL supports encapsulation by requiring message‑passing for the manipulation of instances of user‑defined classes. An instance cannot respond to a message for which it does not have a defined message‑handler.

 

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.

 

One COOL object can respond to a message in a completely different way than another object; this is polymorphism. This is accomplished by attaching message‑handlers with differing actions but which have the same name to the classes of these two objects respectively.

 

Dynamic binding is supported in that an object reference (see section 2.3.1) in a send function call is not bound until run‑time. For example, an instance‑name or variable might refer to one object at the time a message is sent and another at a later time.

2.6.3 Instance‑set Queries and Distributed Actions

In 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 Construct

Ordered 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 assign­ing 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.

 

The syntax of  the deftemplate construct is:

Syntax

(deftemplate <deftemplate-name> [<comment>]

   <slot-definition>*)

 

<slot-definition> ::= <single-slot-definition> |

                      <multislot-definition>

 

<single-slot-definition>

               ::= (slot <slot-name>

                         <template-attribute>*)

 

<multislot-definition>  

               ::= (multislot <slot-name>

                              <template-attribute>*)

 

<template-attribute> ::= <default-attribute> |

                         <constraint-attribute>

 

<default-attribute> 

               ::= (default ?DERIVE | ?NONE | <expression>*) |

                   (default-dynamic <expression>*)

 

Redefining a deftemplate will result in the previous definition being discarded. A deftemplate can not be redefined while it is being used (for example, by a fact or pattern in a rule). A deftemplate can have any number of single or multifield slots. CLIPS always enforces the single and multifield definitions of the deftemplate. For example, it is an error to store (or match) multiple values in a single-field slot.

Example

(deftemplate object

   (slot name)

   (slot location)

   (slot on-top-of)

   (slot weight)

   (multislot contents))

3.1 Slot Default Values

The <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.

 

The default attribute specifies a static default value. The specified expressions are evaluated once when the deftemplate is defined and the result is stored with the deftemplate. The result is assigned to the appropriate slot when a new template fact is asserted. If the keyword ?DERIVE is used for the default value, then a default value is derived from the constraints for the slot (see section 11.5 for more details). By default, the default attribute for a slot is (default ?DERIVE). If the keyword ?NONE is used for the default value, then a value must explicitly be assigned for a slot when an assert is performed. It is an error to assert a template fact without specifying the values for the (default ?NONE) slots.

 

The default‑dynamic attribute is a dynamic default. The specified expressions are evaluated every time a template fact is asserted, and the result is assigned to the appropriate slot.

 

A single‑field slot may only have a single value for its default. Any number of values may be specified as the default for a multifield slot (as long as the number of values satisfies the cardinality attribute for the slot).

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))

 

[TMPLTRHS1] Slot w requires a value because of its (default ?NONE) attribute.

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‑Matching

Single‑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 Attributes

The 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 than 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 a 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 Deftemplates

Asserting 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 Construct

With the deffacts construct, a list of facts can be defined which are automatically asserted whenever the reset command is performed. Facts as­serted 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>]
   <RHS-pattern>*)

 

Redefining a currently existing deffacts causes the previous deffacts with the same name to be removed even if the new definition has errors in it. There may be multiple deffacts constructs and any number of facts (either ordered or deftemplate) may be asserted into the initial fact‑list by each deffacts construct.

 

Dynamic expressions may be included in a fact by embedding the expression directly within the fact. All such expressions are evaluated when CLIPS is reset.

Example

(deffacts startup "Refrigerator Status"
   (refrigerator light on)
   (refrigerator door open)

   (refrigerator temp (get-temp)))

 

Upon startup and after a clear command, CLIPS automatically constructs the following deftemplate and deffacts.

 

(deftemplate initial-fact)

 

(deffacts initial-fact

   (initial-fact))

 

This deffacts provides a convenient method for starting the execution of a system – Rules that are given no conditional element are automatically given a pattern which matches the (initial‑fact) fact.

 

Important Note

Once created, the initial‑fact deffacts and deftemplate are treated just as any other deffacts or deftemplate defined by the user would be—All of the functions and commands appropriate for these constructs can be applied to them. In practice, however, the undeffacts and undeftemplate commands should never be applied to these automatically created constructs since many conditional elements rely on the existence of the initial-fact fact for correct operation. Similarly, the initial-fact fact asserted by the initial-fact deffacts when a reset command is issued, should never be retracted by a program.


Section 5 ‑ Defrule Construct

One of the primary methods of representing knowledge in CLIPS is a rule. A rule is a collec­tion 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 cur­rent state of the system (as represented by the fact‑list and instance‑list) and applies the actions.

 

Throughout this section, the term pattern entity will be used to refer to either a fact or an instance of a user‑defined class.

5.1 Defining Rules

Rules are defined using the defrule construct.

Syntax

(defrule <rule-name> [<comment>]

   [<declaration>]               ; Rule Properties

   <conditional-element>*        ; Left-Hand Side (LHS)
   =>
   <action>*)                    ; Right-Hand Side (RHS)

  

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 per­formed when the LHS of the rule is sat­isfied. 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 ac­tions a rule may have (other than the limitation placed by actual avail­able memory). Actions are performed sequentially if, and only if, all condi­tional elements on the LHS are satisfied.

 

If no conditional elements are on the LHS, the pattern CE (initial‑fact) or (initial‑object) is automatically used. If no ac­tions are on the RHS, the rule can be activated and fired but nothing will happen.

 

As rules are defined, they are incrementally reset. This means that CEs in newly defined rules can be satisfied by pattern entities at the time the rule is defined, in addition to pattern entities created after the rule is defined (see sections 13.1.8, 13.6.9, and 13.6.10 for more details).

Example

(defrule example-rule   "This is an example of a simple rule"
   (refrigerator light on)
   (refrigerator door open)
   =>
   (assert (refrigerator food spoiled)))

5.2 Basic Cycle Of Rule Execution

Once 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 program­mer. 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 pro­vided by CLIPS is used to apply the knowledge to the data. The basic execution cycle is as follows:

 

a)   If the rule firing limit has been reached or there is no current focus, then execution is halted. Otherwise, the top rule on the agenda of the module which is the current focus is selected for execution. If there are no rules on that agenda, then the current focus is removed from the focus stack and the current focus becomes the next module on the focus stack. If the focus stack is empty, then execution is halted, otherwise step a is executed again. See sections 5.4.10.2, 10.6, 12.2, and 13.7 for information on the focus stack and the current focus.

 

b)   The right‑hand side (RHS) actions of the selected rule are executed. The use of the return function on the RHS of a rule may remove the current focus from the focus stack (see sections 10.6 and 12.6.7). The number of rules fired is incremented for use with the rule firing limit.

 

c)   As a result of step b, rules may be activated or deactivated. Activated rules (those rules whose conditions are currently satisfied) are placed on the agenda of the module in which they are defined. The placement on the agenda is determined by the salience of the rule and the current conflict resolution strategy (see sections 5.3, 5.4.10, 13.7.5, and 13.7.6). Deactivated rules are removed from the agenda. If the activations item is being watched (see section 13.2), then an informational message will be displayed each time a rule is activated or deactivated.

 

d)   If dynamic salience is being used, the salience values for all rules on the agenda are reevaluated (see sections 5.4.10, 13.7.9, and 13.7.10). Repeat the cycle beginning with step a.

5.3 Conflict Resolution Strategies

The 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:

 

a)   Newly activated rules are placed above all rules of lower salience and below all rules of higher salience.

 

b)   Among rules of equal salience, the current conflict resolution strategy is used to determine the placement among the other rules of equal salience.

 

c)   If a rule is activated (along with several other rules) by the same assertion or retraction of a fact, and steps a and b are unable to specify an ordering, then the rule is arbitrarily (not randomly) ordered in relation to the other rules with which it was activated. Note, in this respect,  the order in which rules are defined has an arbitrary effect on conflict resolution (which is highly dependent upon the current underlying implementation of rules). Do not depend upon this arbitrary ordering for the proper execution of your rules.

 

CLIPS provides seven conflict resolution strategies: depth, breadth, simplicity, complexity, lex, mea, and random. The default strategy is depth. The current strategy can be set by using the set‑strategy command (which will reorder the agenda based upon the new strategy).

5.3.1 Depth Strategy

Newly 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 Strategy

Newly 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 Strategy

Among 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

 

(defrule example

   (item ?x ?y ?x)

   (test (and (numberp ?x) (> ?x (+ 10 ?y)) (< ?x 100)))

   =>)

 

has a specificity of 5. The comparison to the constant item, the comparison of ?x to its previous binding, and the calls to the numberp, <, and > functions each add one to the specificity for a total of 5. The calls to the and and + functions do not add to the specificity of the rule.

5.3.4 Complexity Strategy

Among rules of the same salience, newly activated rules are placed above all activations of rules with equal or lower specificity.

5.3.5 LEX Strategy

Among 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.

 

If one activation has more pattern entities than the other activation and the compared time tags are all identical, then the activation with more time tags is placed before the other activation on the agenda. If two activations have the exact same recency, the activation with the higher specificity is placed above the activation with the lower specificity. Unlike OPS5, the not conditional elements in CLIPS have pseudo time tags which are used by the LEX conflict resolution strategy. The time tag of a not CE is always less than the time tag of a pattern entity, but greater than the time tag of a not CE that was instantiated after the not CE in question.

 

As an example, the following six activations have been listed in their LEX ordering (where the comma at the end of the activation indicates the presence of a not CE). Note that a fact’s time tag is not necessarily the same as it’s index (since instances are also assigned time tags), but if one fact’s index is greater than another facts’s index, then it’s time tag is also greater. For this example, assume that the time tags and indices are the same.

 

rule-6: f-1,f-4

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

 

Shown following are the same activations with the fact indices sorted as they would be by the LEX strategy for comparison.

 

rule-6: f-4,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 Strategy

Among 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.

 

As an example, the following six activations have been listed in their MEA ordering (where the comma at the end of the activation indicates the presence of a negated pattern).

 

rule-2: f-3,f-1

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 Strategy

Each 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).

 

Usage Note

 

A conflict resolution strategy is an implicit mechanism for specifying the order in which rules of equal salience should be executed. In early expert system tools, this was often the only mechanism provided to specify the order. Because the mechanism is implicit, it’s not possible to determine the programmer’s original intent simply by looking at the code. [Of course in the real world there isn’t a need to guess the original intent because the code is riddled with helpful comments.] Rather than explicitly indicating that rule A should be executed before rule B, the order of execution is implicitly determined by the order in which facts are asserted and the complexity of the rules. The assumption one must make when examining the code is that the original programmer carefully analyzed the rules and followed the necessary conventions so that the rules execute in the appropriate sequence.

 

Because they require explicit declarations, the preferred mechanisms in CLIPS for ordering the execution of rules are salience and modules. Salience allows one to explicitly specify that one rule should be executed before another rule. Modules allow one to explicitly specify that all of the rules in a particular group (module) should be executed before all of the rules in a different group.  Thus, when designing a program the following convention should be followed: if two rules have the same salience, are in the same module, and are activated concurrently, then the order in which they are executed should not matter. For example, the following two rules need correction because they can be activated at the same time, but the order in which they execute matters:

 

(defrule rule-1

   (factoid a)

   =>

   (assert (factoid b)))

  

(defrule rule-2

   ?f <- (factoid a)

   (factoid d)

   =>

   (retract ?f)

   (assert (factoid c)))

 

Programmers should also be careful to avoid overusing salience. Trying to unravel the relationships between dozens of salience values can be just as confusing as the implicit use of a conflict resolution strategy in determining rule execution order. It’s rarely necessary to use more than five to ten salience values in a well-designed program.

 

Most programs should use the default conflict resolution strategy of depth. The breadth, simplicity, and complexity strategies are provided largely for academic reasons (i.e. the study of conflict resolution strategies). The lex and mea strategies are provided to help in converting OPS5 programs to CLIPS.

 

The random strategy is useful for testing. Because this strategy randomly orders activations having the same salience, it is useful in detecting whether the execution order of rules with the same salience effects the program behavior. Before running a program with the random strategy, first seed the random number generator using the seed function. The same seed value can be subsequently be used if it is necessary to replicate the results of the program run.

5.4 LHS Syntax

This 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).

 

Syntax

<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 Element

Pattern 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.

 

The first field of any pattern must be a symbol and can not use any other constraints. This first field is used by CLIPS to determine if the pattern applies to an ordered fact, a template fact, or an instance. The symbol object is reserved to indicate an object pattern. Any other symbol used must correspond to a deftemplate name (or an implied deftemplate will be created). Slot names must also be symbols and cannot contain any other constraints.

 

For object and deftemplate patterns, a single field slot can only contain one field constraint and that field constraint must only be able to match a single field (no multifield wildcards or variables). A multifield slot can contain any number of field constraints.

 

The examples and syntax shown in the following sections will be for ordered and deftemplate fact patterns. Section 5.4.1.7 will discuss differences between deftemplate patterns and object patterns. The following constructs are used by the examples.

 

(deffacts data-facts

  (data 1.0 blue "red")

  (data 1 blue)

  (data 1 blue red)

  (data 1 blue RED)

  (data 1 blue red 6.9))

 

(deftemplate person

  (slot name)

  (slot age)

  (multislot friends))

 

(deffacts people

  (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 Constraints

The 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.

 

Syntax

An ordered pattern conditional element containing only literals has the following basic syntax:

 

(<constant-1> ... <constant-n>)

 

A deftemplate pattern conditional element containing only literals has the following basic syntax:

 

(<deftemplate-name> (<slot-name-1> <constant-1>)
                                       
                                       
                                       
                    (<slot-name-n> <constant-n>))

Example 1

This example utilizes the data‑facts deffacts shown in section 5.4.1.

 

CLIPS> (clear)

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> (clear)

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 Multifield

CLIPS has two wildcard symbols that may be used to match fields in a pat­tern. CLIPS in­terprets these wildcard symbols as standing in place of some part of a pattern entity. The single‑field wild­card, 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.

 

Syntax

An ordered pattern conditional element containing only literals and wildcards has the following basic syntax:

 

(<constraint-1> ... <constraint-n>)

 

where

 

<constraint> ::= <constant> | ? | $?

 

A deftemplate pattern conditional element containing only literals and wildcards has the following basic syntax:

 

(<deftemplate-name> (<slot-name-1> <constraint-1>)
                                       
                                       
                                       
                    (<slot-name-n> <constraint-n>))

Example 1

This example utilizes the data‑facts deffacts shown in section 5.4.1.

 

CLIPS> (clear)

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> (clear)

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>

 

Multifield wildcard and literal constraints can be combined to yield some powerful pattern‑matching capabilities. A pattern to match all of the facts that have the symbol YELLOW in any field (other than the first) could be written as

 

(data $? YELLOW $?)

 

Some examples of what this pattern would match are

 

(data YELLOW blue red green)

(data YELLOW red)

(data red YELLOW)

(data YELLOW)

(data YELLOW data YELLOW)

 

The last fact will match twice since YELLOW appears twice in the fact. The use of multifield wildcards should be confined to cases of patterns in which the single‑field wildcard cannot create a pattern that satisfies the match required, since the multifield wildcard produces every possible match combination that can be derived from a pattern entity. This derivation of matches requires a significant amount of time to perform when compared to the time needed to perform a single‑field match.

5.4.1.3 Variables Single‑ and Multifield

Wildcard 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.

 

Syntax

Expanding on the syntax definition given in section 5.4.1.2 now gives:

 

<constraint> ::= <constant> | ? | $? |

                 <single-field-variable> |

                 <multifield-variable>

 

<single-field-variable> ::= ?<variable-symbol>

 

<multifield-variable>   ::= $?<variable-symbol>

 

where <variable‑symbol> is similar to a symbol, except that it must start with an alphabetic char­acter. Double quotes are not allowed as part of a variable name; i.e. a string cannot be used for a variable name. The rules for pattern‑matching are similar to those for wildcard symbols. On its first appearance, a variable acts just like a wildcard in that it will bind to any value in the field(s). However, later appearances of the variable require the field(s) to match the binding of the variable. The binding will only be true within the scope of the rule in which it occurs. Each rule has a private list of variable names with their associated values; thus, variables are local to a rule. Bound vari­ables can be passed to external functions. The $ operator has special significance on the LHS as a pattern‑matching operator to indicate that zero or more fields need to be matched. In other places (such as the RHS of a rule), the $ in front of a variable indicates that sequence expansion should take place before calling the function. Thus, when passed as parameters in function calls (either on the LHS or RHS of a rule), multifield variables should not be preceded by the $ (unless sequence expansion is desired). All other uses of a multifield variable on the LHS of a rule, however, should use the $. It is illegal to use a multifield variable in a single field slot of a deftemplate/object pattern.

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>

 

Once the initial binding of a variable occurs, all references to that variable have to match the value that the first binding matched. This applies to both single‑ and multi­field variables. It also applies across patterns.

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 Constraints

Three 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 com­bined 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:

 

<term-1>&<term-2> ... &<term-3> 

 

<term-1>|<term-2> ... |<term-3>

 

~<term>

 

where <term> could be a single‑field variable, multifield variable, constant, or connected constraint.

 

Syntax

Expanding on the syntax definition given in section 5.4.1.3 now gives:

 

<constraint> ::= ? | $? | <connected-constraint>

 

<connected-constraint>

             ::= <single-constraint> |

                 <single-constraint> & <connected-constraint> |

                 <single-constraint> | <connected-constraint>

 

<single-constraint> ::= <term> | ~<term>

 

<term> ::= <constant> |

           <single-field-variable> |

           <multifield-variable>

 

The & constraint typically is used only in conjunction with other constraints or variable bindings. Notice that connective constraints may be used together and/or with variable bindings. If the first term of a connective constraint is the first occurrence of a variable name, then the field will be constrained only by the remaining field constraints. The variable will be bound to the value of the field. If the variable has been bound previously, it is considered an additional con­straint along with the remaining field constraints; i.e., the field must have the same value already bound to the variable and must satisfy the field constraints.

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 Constraints

Sometimes 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>

 

Syntax

Expanding on the syntax definition given in section 5.4.1.4 now gives:

 

<term> ::= <constant> |

           <single-field-variable> |

           <multifield-variable> |

           :<function-call>

 

Multiple predicate constraints may be used to constrain a single field. Several predicate functions are provided by CLIPS (see section 12.2). Users also may develop their own predicate functions.

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 Constraints

It 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 pat­tern. (This constraint is different from the com­parison 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 pat­terns 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>

 

Syntax

Expanding on the syntax definition given in section 5.4.1.5 now gives:

 

<term> ::= <constant> |

           <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 Patterns

Instances 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.

 

When an instance is created or deleted, all patterns applicable to that object are updated. However, when a slot is changed, only those patterns which explicitly match on that slot are affected. Thus, one could use logical dependencies to hook to a change to a particular slot (rather than a change to any slot, which is all that is possible with deftemplates).

 

Changes to non‑reactive slots or instances of non‑reactive classes (see sections 9.3.2.2 and 9.3.3.7) will have no effect on rules. Also Rete network activity will not be immediately apparent after changes to slots are made if pattern‑matching is being delayed through the use of the make‑instance, i.initialize‑instance;, i.modify‑instance;, i.message‑modify‑instance;, i.duplicate‑instance;, i.message‑duplicate‑instance; or object‑pattern‑match‑delay functions.

 

Syntax

<object-pattern>       ::= (object <attribute-constraint>*)

 

<attribute-constraint> ::= (is-a <constraint>) |

                           (name <constraint>) |

                           (<slot-name> <constraint>*)

 

The is‑a constraint is used for specifying class constraints such as “Is this object a member of class FOO?”. The is‑a constraint also encompasses subclasses of the matching classes unless specifically excluded by the pattern. The name constraint is used for specifying a specific instance on which to pattern‑match. The evaluation of the name constraint must be of primitive type instance‑name, not symbol. Multifield constraints (such as $?) cannot be used with the is‑a or name constraints. Other than these special cases, constraints used in object slots work similarly to constraints used in deftemplate slots. As with deftemplate patterns, slot names for object patterns must be symbols and can not contain any other constraints.

Example 1

The following rules illustrate pattern‑matching on an object's class.

 

(defrule class-match-1

  (object)

  =>)

 

(defrule class-match-2

  (object (is-a FOO))

  =>)

 

(defrule class-match-3

  (object (is-a FOO | BAR))

  =>)

 

(defrule class-match-4

  (object (is-a ?x))

  (object (is-a ~?x))

  =>)

 

Rule class‑match‑1 is satisified by all instances of any reactive class. Rule class‑match‑2 is satisfied by all instances of class FOO. Rule class‑match‑3 is satisfied by all instances of class FOO or BAR. Rule class‑match‑4 will be satisfied by any two instances of mutually exclusive classes.

Example 2

The following rules illustrate pattern‑matching on various attributes of an object's slots.

 

(defrule slot-match-1

  (object (width))

  =>)

 

(defrule slot-match-2

  (object (width ?))

  =>)

 

(defrule slot-match-3

  (object (width $?))

  =>)

 

Rule slot‑match‑1 is satisfied by all instances of reactive classes that contain a reactive width slot with a zero length multifield value. Rule slot‑match‑2 is satisfied by all instances of reactive classes that contain a reactive single or multifield width slot that is bound to a single value. Rule slot‑match‑3 is satisfied by all instances of reactive classes that contain a reactive single or multifield width slot that is bound to any number of values. Note that a slot containing a zero length multifield value would satisfy rules slot‑match‑1 and slot‑match‑3, but not rule slot‑match‑2 (because the value's cardinality is zero).

Example 3

The following rules illustrate pattern‑matching on the slot values of an object.

 

(defrule value-match-1

  (object (width 10)

  =>)

 

(defrule value-match-2

  (object (width ?x&:(> ?x 20)))

  =>)

 

(defrule value-match-3

  (object (width ?x) (height ?x))

  =>)

 

Rule value‑match‑1 is satisified by all instances of reactive classes that contain a reactive width slot with value 10. Rule value‑match‑2 is satisfied by all instances of reactive classes that contain a reactive width slot that has a value greater than 20. Rule value‑match‑3 is satisfied by all instances of reactive classes that contain a reactive width and height slots with the same value.

5.4.1.8 Pattern‑Addresses

Certain 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>

 

The left arrow, <‑, is a required part of the syntax. A variable bound to a fact‑address or instance‑address can be compared to other variables or passed to external functions. Variables bound to a fact or instance‑address may later be used to constrain fields within a pattern CE, however, the reverse is not allowed. It is an error to bind a varible to a not CE.

Examples

(defrule dummy

   (data 1)

   ?fact <- (dummy pattern)

   =>

   (retract ?fact))

 

(defrule compare-facts-1   

   ?f1 <- (color ~red)

   ?f2 <- (color ~green)

   (test (neq ?f1 ?f2))

   =>

   (printout t "Rule fires from different facts" crlf))

 

(defrule compare-facts-2   

   ?f1 <- (color ~red)

   ?f2 <- (color ~green&:(neq ?f1 ?f2))

   =>

   (printout t "Rule fires from different facts" crlf))

 

(defrule print-and-delete-all-objects

   ?ins <- (object)

   =>

   (send ?ins print)

   (unmake-instance ?ins))

5.4.2 Test Conditional Element

Field 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 oc­curred in any manner. Mathematical comparisons on variables (e.g., is the differ­ence 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 vari­ables in any way that the user desires.

 

Any kind of external function may be embedded within a test conditional element (or within field constraints). User‑defined predicate functions must take arguments as defined in the Advanced Programming Guide. Sev­eral predicate functions are provided by CLIPS (see section 12.1).

Syntax

<test-CE> ::= (test <function-call>)

 

Since the symbol test is used to indicate this type of conditional element, rules may not use the symbol test as the first field in a pattern CE. A test CE is evaluated when all proceeding CEs are satisfied. This means that a test CE will be evaluated more than once if the proceeding CEs can be satisfied by more than one group of pattern entities. In order to cause the reevaluation of a test CE, a pattern entity matching a CE prior to the test CE must be changed. The use of test CEs can cause additional CEs to be added to the rule. In addition, test CEs may also be automatically reordered by CLIPS. See section 5.4.9 for more details.

Example 1

This example checks to see if the difference between two numbers is greater than or equal to three:

 

CLIPS> (clear)

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> (clear)

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>

 

Important Note

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. In addition, the initial-fact fact asserted or initial-object instance created when a reset command is issued should never be retracted or deleted by a program.

5.4.3 Or Conditional Element

The 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 condi­tional 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 sim­ilar 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
   (error-status unknown)
   (or (temp high)
       (valve broken)

       (pump (status off)))
   =>
   (printout t "The system has a fault." crlf))

 

Note that the above example is exactly equivalent to the following three (separate) rules:

 

(defrule system-fault
   (error-status unknown)
   (pump (status off))
   =>
   (printout t "The system has a fault." crlf))

 

(defrule system-fault
   (error-status unknown)
   (valve broken)
   =>
   (printout t "The system has a fault." crlf))

 

(defrule system-fault
   (error-status unknown)
   (temp high)
   =>
   (printout t "The system has a fault." crlf))

5.4.4 And Conditional Element

CLIPS 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 condi­tions 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
   (error-status confirmed)
   (or (and (temp high)
            (valve closed))
       (and (temp low)
            (valve open)))
   =>
   (printout t "The system is having a flow problem." crlf))

 

An and CE that has a test or not CE as its first CE has the pattern (initial‑fact) or (initial‑object) added as the first CE. Note that the LHS of any rule is enclosed within an implied and CE. For example, the following rule

 

(defrule nothing-to-schedule

  (not (schedule ?))

  =>

  (printout t "Nothing to schedule." crlf))

 

is converted to

 

(defrule nothing-to-schedule

  (and (initial-fact)

       (not (schedule ?)))

  =>

  (printout t "Nothing to schedule." crlf))

5.4.5 Not Conditional Element

Sometimes 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 con­straints may be used within the negated pattern.

Syntax

<not-CE> ::= (not <conditional-element>)

 

Only one CE may be negated at a time. Multiple patterns may be negated by using multiple not CEs. Care must be taken when combining not CEs with or and and CEs; the results are not always obvi­ous!  The same holds true for variable bindings within a not CE. Previously bound variables may be used freely inside of a not CE. However, variables bound for the first time within a not CE can be used only in that pattern.

Examples

(defrule high-flow-rate
   (temp high)
   (valve open)
   (not (error-status confirmed))
   =>
   (printout t "Recommend closing of valve due to high temp"

               crlf))

 

   (defrule check-valve
   (check-status ?valve)
   (not (valve-broken ?valve))
   =>
   (printout t "Device " ?valve " is OK" crlf))

 

(defrule double-pattern
   (data red)

   (not (data red ?x ?x))
   =>
   (printout t "No patterns with red green green!" crlf ))

 

A not CE that contains a single test CE is converted such that the test CE is contained within an and CE and is preceded by the (initial‑fact) or (initial‑object) pattern. For example, the following conditional element

 

(not (test (> ?time-1 ?time-2)))

 

is converted to

 

(not (and (initial-fact)

          (test (> ?time-1 ?time-2))))

 

Note that it is much simpler just to convert the test CE to the following format:

 

(test (not (> ?time-1 ?time-2)))

 

Important Note

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. In addition, the initial-fact fact asserted or initial-object instance created when a reset command is issued should never be retracted or deleted by a program.

5.4.6 Exists Conditional Element

The 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>+)

 

The exists CE is implemented by replacing the exists keyword with two nested not CEs. For example, the following rule

 

(defrule example

   (exists (a ?x) (b ?x))

   =>)

 

is equivalent to the rule below

 

(defrule example

   (not (not (and (a ?x) (b ?x))))

   =>)

 

Because of the way the exists CE is implemented using not CEs, the restrictions which apply to CEs found within not CEs (such as binding a pattern CE to a fact‑address) also apply to the CEs found within an exists CE.

Example

Given the following constructs,

 

CLIPS> (clear)

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>

 

the following commands illustrate that even though there are three facts which can match the second CE in the save‑the‑day rule, there is only one partial match generated.

 

CLIPS> (reset)

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>

 

Important Note

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. In addition, the initial-fact fact asserted or initial-object instance created when a reset command is issued should never be retracted or deleted by a program.

5.4.7 Forall Conditional Element

The 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>+)

 

The forall CE is implemented by replacing the forall keyword with combinations of not and and CEs. For example, the following rule

 

(defrule example

   (forall (a ?x) (b ?x) (c ?x))

   =>)

 

is equivalent to the rule below

 

(defrule example

   (not (and (a ?x)

             (not (and (b ?x) (c ?x)))))

   =>)

 

Because of the way the forall CE is implemented using not CEs, the restrictions which apply to CE found within not CEs (such as binding a pattern CE to a fact‑address) also apply to the CEs found within an forall CE.

Example

The following rule determines if every student has passed in reading, writing, and arithmetic by using the forall CE.

 

CLIPS> (clear)

CLIPS>

(defrule all-students-passed

   (forall (student ?name)

           (reading ?name)

           (writing ?name)

           (arithmetic ?name))

   =>

   (printout t "All students passed." crlf))

CLIPS>

 

The following commands illustrate how the forall CE works in the all‑students‑passed rule. Note that initially the all‑students‑passed rule is satisfied because there are no students.

 

CLIPS> (reset)

CLIPS> (agenda)

0      all-students-passed: f-0,

For a total of 1 activation.

CLIPS>

 

After the (student Bob) fact is asserted, the rule is no longer satisfied since Bob has not passed reading, writing, and arithmetic.

 

CLIPS> (assert (student Bob))

<Fact-1>

CLIPS> (agenda)

CLIPS>

 

The rule is still not satisfied after Bob has passed reading and writing, since he still has not passed arithmetic.

 

CLIPS> (assert (reading Bob) (writing Bob))

<Fact-3>

CLIPS> (agenda)

CLIPS>

 

Once Bob has passed arithmetic, the all‑students‑passed rule is reactivated.

 

CLIPS> (assert (arithmetic Bob))

<Fact-4>

CLIPS> (agenda)

0      all-students-passed: f-0,

For a total of 1 activation.

CLIPS>

 

If a new student is asserted, then the rule is taken off the agenda, since John has not passed reading, writing, and arithmetic.

 

CLIPS> (assert (student John))

<Fact-5>

CLIPS> (agenda)

CLIPS>

 

Removing both student facts reactivates the rule again.

 

CLIPS> (retract 1 5)

CLIPS> (agenda)

0      all-students-passed: f-0,

For a total of 1 activation.

CLIPS>

 

Important Note

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. In addition, the initial-fact fact asserted or initial-object instance created when a reset command is issued should never be retracted or deleted by a program.

5.4.8 Logical Conditional Element

The 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.

 

If a pattern entity is created without logical support (e.g., from a deffacts, definstaces, as a top‑level command, or from a rule without any logical patterns), then the pattern entity has unconditional support. Unconditionally supporting a pattern entity removes all logical support (without causing the removal of  the pattern entity). In addition, further logical support for an unconditionally supported pattern entity is ignored. Removing a rule that generated logical support for a pattern entity, removes the logical support generated by that rule (but does not cause the removal of the pattern entity if no logical support remains).

Syntax

<logical-CE> ::= (logical <conditional-element>+)

 

The logical CE groups patterns together exactly as the explicit and CE does. It may be used in conjunction with the and, or, and not CEs. However, only the first N patterns of a rule can have the logical CE applied to them. For example, the following rule is legal

 

(defrule ok

   (logical (a))

   (logical (b))

   (c)

   =>

   (assert (d)))

 

whereas the following rules are illegal

 

(defrule not-ok-1

   (logical (a))

   (b)

   (logical (c))

   =>

   (assert (d)))

 

(defrule not-ok-2

   (a)

   (logical (b))

   (logical (c))

   =>

   (assert (d)))

 

(defrule not-ok-3

   (or (a)

       (logical (b)))

   (logical (c))

   =>

   (assert (d)))

Example

Given the following rules,

 

CLIPS> (clear)

CLIPS>

(defrule rule1

   (logical (a))

   (logical (b))

   (c)

   =>

   (assert (g) (h)))

CLIPS>

(defrule rule2

   (logical (d))

   (logical (e))

   (f)

   =>

   (assert (g) (h)))

CLIPS>

 

the following commands illustrate how logical dependencies work.

 

CLIPS> (watch facts)

CLIPS> (watch activations)

CLIPS. (watch rules)

CLIPS> (assert (a) (b) (c) (d) (e) (f))

==> f-0     (a)

==> f-1     (b)

==> f-2     (c)

==> 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>

 

As mentioned in section 5.4.1.7, the logical CE can be used with an object pattern to create pattern entities which are logically dependent on changes to specific slots in the matching instance(s) rather than all slots. This cannot be accomplished with template facts because a change to a template fact slot actually involves the retraction of the old template fact and the assertion of a new one, whereas a change to an instance slot is done in place. The example below illustrates this behavior:

 

CLIPS> (clear)

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 CEs

Under 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

 

(initial-fact)

 

and the initial‑object pattern is

 

(object (is-a INITIAL-OBJECT) (name [initial-object]))

5.4.9.1 Rules Without Any LHS Pattern CEs

The 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

 

(defrule example-1

   =>)

 

would be changed as follows.

 

(defrule example-1

   (initial-fact)

   =>)

5.4.9.2 Test and Not CEs as the First CE of an And CE

Test 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

 

(defrule example-2

   (test (> 80 (startup-value)))

   =>)

 

(defrule example-3

   (test (> 80 (startup-value)))

   (object (is-a MACHINE))

   =>)

 

(defrule example-4

   (machine ?x)

   (not (and (not (part ?x ?y))

             (inventoried ?x)))

   =>)

 

would be changed as follows.

 

(defrule example-2

   (initial-fact)

   (test (> 80 (startup-value)))

   =>)

 

(defrule example-3

   (object (is-a INITIAL-OBJECT) (name [initial-object]))

   (test (> 80 (startup-value)))

   (object (is-a MACHINE))

   =>)

 

(defrule example-4

   (machine ?x)

   (not (and (initial-fact)

             (not (part ?x ?y))

             (inventoried ?x)))

   =>)

5.4.9.3 Test CEs Following Not CEs

Test 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

 

(defrule example

   (a ?x)

   (not (b ?x))

   (test (> ?x 5))

   =>)

 

would be changed as follows.

 

(defrule example

   (a ?x)

   (test (> ?x 5))

   (not (b ?x))

   =>)

5.4.9.4 Or CEs Following Not CEs

If 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

 

(defrule example

   (a ?x)

   (not (or (b ?x)

            (c ?x)))

   =>)

 

would be changed as follows.

 

(defrule example

   (a ?x)

   (and (not (b ?x))

        (not (c ?x)))

   =>)

5.4.9.5 Notes About Pattern Addition and Reordering

There 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.

 

Important Note

The initial-fact fact asserted or initial-object instance created when a reset command is issued should never be retracted or deleted by a program because this will cause the initial-fact pattern and initial-object pattern to be unmatched.

5.4.10 Declaring Rule Properties

This feature allows the properties or characteristics of a rule to be defined. The char­acter­istics are declared on the LHS of a rule using the declare keyword. A rule may only have one declare statement and it must appear be­fore the first conditional element on the LHS (as shown in section 5.1).

Syntax

<declaration> ::= (declare <rule-property>+)

 

<rule-property> ::= (salience <integer-expression>) |

                    (auto-focus <boolean-symbol>)

 

<boolean-symbol> ::= TRUE | FALSE

5.4.10.1 The Salience Rule Property

The 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
   (declare (salience 99))     
   (fire test-1)
   =>
   (printout t "Rule test-1 firing." crlf))

 

(defrule test-2
   (declare (salience (+ ?*constraint-salience* 10)))

   (fire test-2)
   =>
   (printout t "Rule test-2 firing." crlf))

 

Salience values can be evaluated at one of three times: when a rule is defined, when a rule is activated, and every cycle of execution (the latter two situations are referred to as dynamic salience). By default, salience values are only evaluated when a rule is defined. The set‑salience‑evaluation command can be used to change this behavior. Note that each salience evaluation method encompasses the previous method (i.e. if saliences are evaluated every cycle, then they are also evaluated when rules are activated or defined).

 

Usage Note

 

Despite the large number of possible values, with good design there’s rarely a need for more than five salience values in a simple program and ten salience values in a complex program. Defining the salience values as global variables allows you to specify and document the values used by your program in a centralized location and also makes it easier to change the salience of a group of rules sharing the same salience value:

 

(defglobal ?*high-priority* = 100)

 

(defglobal ?*low-priority* = -100)

 

(defrule rule-1

   (declare (salience ?*high-priority*))

   =>)

  

(defrule rule-2

   (declare (salience ?*low-priority*))

   =>)

5.4.10.2 The Auto‑Focus Rule Property

The 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
   (declare (auto-focus TRUE))
   (person (name ?name) (age ?x&:(< ?x 0)))
   =>
   (printout t ?name " has a bad age value." crlf))


Section 6 ‑ Defglobal Construct

With 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>*)

 

<global-assignment> ::= <global-variable> = <expression>

 

<global-variable>   ::= ?*<symbol>*

 

There may be multiple defglobal constructs and any number of global variables may be defined in each defglobal statement. The optional <defmodule‑name> indicates the module in which the defglobals will be defined. If none is specified, the globals will be placed in the current module. If a variable was defined in a previous defglobal construct, its value will be replaced by the value found in the new defglobal construct. If an error is encountered when defining a defglobal construct, any global variable definitions that occurred before the error was encountered will still remain in effect.

 

Commands that operate on defglobals such as ppdefglobal and undefglobal expect the symbolic name of the global without the astericks (e.g. use the symbol max when you want to refer to the global variable ?*max*).

 

Global variables may be used anyplace that a local variable could be used (with two exceptions). Global variables may not be used as a parameter variable for a deffunction, defmethod, or message-handler. Global variables may not be used in the same way that a local variable is used on the LHS of a rule to bind a value. Therefore, the following rule is illegal

 

(defrule example

   (fact ?*x*)

   =>)

 

The following rule, however, is legal.

 

(defrule example

   (fact ?y&:(> ?y ?*x*))

   =>)

 

Note that this rule will not necessarily be updated when the value of ?*x* is changed. For example, if ?*x* is 4 and the fact (fact 3) is added, then the rule is not satisfied. If the value of ?*x* is now changed to 2, the rule will not be activated.

Example

(defglobal

   ?*x* = 3

   ?*y* = ?*x*

   ?*z* = (+ ?*x* ?*y*)

   ?*q* = (create$ a b c))

 

Usage Note

 

The inappropriate use of globals within rules is quite often the first resort of beginning programmers who have reached an impasse in developing a program because they do not fully understand how rules and pattern-matching work. As it relates to this issue, the following sentence from the beginning of this section is important enough to repeat:

 

Global variables can be accessed as part of the pattern‑matching process, but changing them does not invoke the pattern‑matching process.

 

Facts and instances are the primary mechanism that should be used to pass information from one rule to another specifically because they do invoke pattern-matching. A change to a slot value of a fact or instance will trigger pattern-matching ensuring that a rule is aware of the current state of that fact or instance. Since a change to a global variable does not trigger pattern‑matching, it is possible for a rule to remain activated based on a past value of a global variable which is undesirable in most situations.

 

It’s worth pointing out that facts and instances are no less ‘global’ in nature than global variables. Just as a rule can access any global variable that’s visible (i.e. it hasn’t been hidden through the use of modules), so too can it access any fact or instance belonging to a deftemplate or defclass that’s visible. In the case of a fact, one can either pattern-match for the fact on the LHS of a rule or use the fact-set query functions from the RHS of a rule. In the case of an instance, pattern-matching and instance-set query functions can also be used, and in addition an instance can be directly referenced by name just as a global variable can.

Common Problem

One of the more common situations in which it is tempting to use global variables is collecting a group of slot values from a fact. First attempts at rules to accomplish this task often loop endlessly because of rules inadvertently retriggered by changes. For example, the following rule will loop endlessly because the new collection fact asserted will create an activation with the same factoid fact that was just added to the collection fact:

 

(defrule add-factoid

   (factoid ?data)

   ?c <- (collection $?collection)

   =>

   (retract ?c)

   (assert (collection ?collection ?data)))

 

This problem can be corrected by removing the factoid fact just added to the collection fact:

 

(defrule add-factoid

   ?f <- (factoid ?data)

   ?c <- (collection $?collection)

   =>

   (retract ?f ?c)

   (assert (collection ?collection ?data)))

 

Retracting the factoid facts, however, isn’t a viable solution if these facts are needed by other rules. A non-destructive approach makes use of temporary facts created by a helper rule:

 

(defrule add-factoid-helper

   (factoid ?data)

   =>

   (assert (temp-factoid ?data)))

  

(defrule add-factoid

   ?f <- (temp-factoid ?data)

   ?c <- (collection $?collection)

   =>

   (retract ?f ?c)

   (assert (collection ?collection ?data)))

 

It certainly looks simpler, however, to use a global variable to collect the slot values:

 

(defglobal ?*collection* = (create$))

 

(defrule add-factoid

   (factoid ?data)

   =>

   (bind ?*collection* (create$ ?*collection* ?data)))

 

Again, the drawback to this approach is that changes to a global variable do not trigger pattern‑matching, so in spite of its greater complexity the  fact-based approach is still preferable.

 

Although it’s important to understand how each of the previous approaches work, they’re not practical solutions. If there are 1000 factoid facts, the add-factoid/add-factoid-helper rules will each fire 1000 times generating and retracting 2000 facts. The best solution is to use the fact-set query functions to iterate over all of the factoid facts and generate the collection fact as the result of a single rule firing:

 

(defrule collect-factoids

   (collect-factoids)

   =>

   (bind ?data (create$))

   (do-for-all-facts ((?f factoid)) TRUE

      (bind ?data (create$ ?data ?f:implied)))

   (assert (collection ?data)))

 

With this approach, the collection fact is available for pattern-matching with the added benefit that there are no intermediate results generated in creating the fact. Typically if other rules are waiting for the finished result of the collection, they would need to have lower salience so that they aren’t fired for the intermediate results:

 

(defrule print-factoids

   (declare (salience -10))

   (collection $?data)

   =>

   (printout t "The collected data is " ?data crlf))

 

If the factoid facts are collected by a single rule firing, then the salience declaration is unnecessary.

Appropriate Uses

The primary use of global variables (in conjunction with rules) is in making a program easier to maintain. It is a rare situation where a global variable is required in order to solve a problem. One appropriate use of global variables is defining salience values shared among multiple rules:

 

(defglobal ?*high-priority* = 100)

 

(defrule rule-1

   (declare (salience ?*high-priority*))

   =>)

  

(defrule rule-2

   (declare (salience ?*high-priority*))

   =>)

 

Another use is defining constants used on the LHS or RHS of a rule:

 

(defglobal ?*week-days* =

   (create$ monday tuesday wednesday thursday friday saturday sunday))

  

(defrule invalid-day

   (day ?day&:(not (member$ ?day ?*week-days*)))

   =>

   (printout t ?day " is invalid" crlf))

  

(defrule valid-day

   (day ?day&:(member$ ?day ?*week-days*))

   =>

   (printout t ?day " is valid" crlf))

 

A third use is passing information to a rule when it is desirable not to trigger pattern-matching. In the following rule, a global variable is used to determine whether additional debugging information is printed:

 

(defglobal ?*debug-print* = nil)

 

(defrule rule-debug

   ?f <- (info ?info)

   =>

   (retract ?f)

   (printout ?*debug-print* "Retracting info " ?info crlf))

 

If ?*debug-print* is set to nil, then the printout statement will not display any information. If the ?*debug-print* is set to t, then debugging information will be sent to the screen. Because ?*debug-print* is a global, it can be changed interactively without causing rules to be reactivated. This is useful when stepping through a program because it allows the level of information displayed to be changed without effecting the normal flow of the program.

 

It’s possible, but a little more verbose, to achieve this same functionality using instances rather than global variables:

 

(defclass DEBUG-INFO

   (is-a USER)

   (slot debug-print))

  

(definstances debug

   ([debug-info] of DEBUG-INFO (debug-print nil)))

  

(defrule rule-debug

   ?f <- (info ?info)

   =>

   (retract ?f)

   (printout (send [debug-info] get-debug-print) "Retracting info " ?info crlf))

 

Unlike fact slots, changes to a slot of an instance won’t trigger pattern matching in a rule unless the slot is specified on the LHS of that rule, thus you have explicit control over whether an instance slot triggers pattern-matching. The following rule won’t be retriggered if a change is made to the debug-print slot:

 

(defrule rule-debug

   ?f <- (info ?info)

   (object (is-a DEBUG-INFO) (name ?name))

   =>

   (retract ?f)

   (printout (send ?name get-debug-print) "Retracting info " ?info crlf))

 

This is a generally applicable technique and can be used in many situations to prevent rules from inadvertently looping when slot values are changed.


Section 7 ‑ Deffunction Construct

With 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.

 

A deffunction is comprised of five elements: 1) a name, 2) an optional comment, 3) a list of zero or more required parameters, 4) an optional wildcard parameter to handle a variable number of arguments and 5) a sequence of actions, or expressions, which will be executed in order when the deffunction is called.

Syntax

(deffunction <name> [<comment>]

   (<regular-parameter>* [<wildcard-parameter>])

   <action>*)

 

<regular-parameter>     ::= <single-field-variable>

<wildcard-parameter>    ::= <multifield-variable>

 

A deffunction must have a unique name different from all other system functions and generic functions. In particular, a deffunction cannot be overloaded like a system function (see section 8 for more detail). A deffunction must be declared prior to being called from another deffunction, generic function method, object message‑handler, rule, or the top level. The only exception is a self recursive deffunction.

 

A deffunction 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 deffunction. Each of these parameters may be referenced like a normal single‑field variable within the actions of the deffunction. If a wildcard parameter is present, the deffunction may be passed any number of arguments greater than or equal to the minimum. If no wildcard parameter is present, then the deffunction must be passed exactly the number of arguments specified by the regular parameters. All arguments to a deffunction 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 nth, can be applied to the wildcard parameter.

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>

 

When a deffunction is called, its actions are executed in order. The return value of a deffunction is the evaluation of the last action. If a deffunction has no actions, its return value is the symbol FALSE. If an error occurs while the deffunction is executing, any actions not yet executed will be aborted, and the deffunction will return the symbol FALSE.

 

Deffunctions may be self and mutually recursive. Self recursion is accomplished simply by calling the deffunction from within its own actions.

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))))))

 

Mutual recursion between two deffunctions requires a forward declaration of one of the deffunctions. A forward declaration is simply a declaration of the deffunction without any actions. In the following example, the deffunction foo is forward declared so that it may be called by the deffunction bar. Then the deffunction foo is redefined with actions that call the deffunction bar.

Example

(deffunction foo ())

(deffunction bar ()

   (foo))

(deffunction foo ()

   (bar))

 

Care should be taken with recursive deffunctions; too many levels of recursion can lead to an overflow of stack memory (especially on PC‑type machines).


Section 8 ‑ Generic Functions

With the defgeneric and defmethod constructs, new generic functions 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.

 

Generic functions can have system functions and user‑defined external functions as implicit methods. For example, an overloading of the “+” operator to handle strings consists of two methods: 1) an implicit one which is the system function handling numerical addition, and 2) an explicit  (user‑defined) one handling string concatenation. Deffunctions, however, may not be methods of generic functions because they are subsumed by generic functions anyway. Deffunctions are only provided so that basic new functions can be added directly in CLIPS without the concerns of overloading. For example, a generic function which has only one method that restricts only the number of arguments is equivalent to a deffunction.

 

In most cases, generic function methods are not called directly (the function call‑specific‑method described in section 12.15.8 can be used to do so, however). CLIPS recognizes that a function call is generic and uses the generic function’s arguments to find and execute the appropriate method. This process is termed the generic dispatch.

8.1 Note on the Use of the Term Method

Most 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‑handler is 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 Functions

A 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 Definitions

If 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 Function

A 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.

 

Syntax

(defgeneric <name> [<comment>])

 

(defmethod <name> [<index>] [<comment>]

   (<parameter-restriction>* [<wildcard-parameter-restriction>])

   <action>*)

 

<parameter-restriction> ::=

                        <single-field-variable> |

                        (<single-field-variable> <type>* [<query>])

 

<wildcard-parameter-restriction>              ::=

                        <multifield-variable> |

                        (<multifield-variable> <type>* [<query>])

 

<type>           ::= <class-name>

<query>   ::= <global-variable> |

                     <function-call>

 

A generic function must be declared, either by a header or a method, prior to being called from another generic function method, deffunction, object message‑handler, rule, or the top level. The only exception is a self recursive generic function.

8.4.1 Generic Function Headers

A 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 Indices

A 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 Restrictions

Each 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.

 

A parameter that has no restrictions means that the method will accept any argument in that position. However, each method of a generic function must have parameter restrictions that make it distinguishable from all of the other methods so that the generic dispatch can tell which one to call at run‑time. If there are no applicable methods for a particular generic function call, CLIPS will generate an error (see section 8.5.4 for more detail).

 

A type restriction allows the user to specify a list of types (or classes), one of which must match (or be a superclass of) the class of the generic function argument. If COOL is not installed in the current CLIPS configuration, the only types (or classes) available are: OBJECT, PRIMITIVE, LEXEME, SYMBOL, STRING, NUMBER, INTEGER, FLOAT, MULTIFIELD, FACT‑ADDRESS and EXTERNAL‑ADDRESS. Section 9 describes each of these system classes. With COOL, INSTANCE, INSTANCE‑ADDRESS, INSTANCE‑NAME, USER, INITIAL‑OBJECT and any user‑defined classes are also available. Generic functions which use only the first group of types in their methods will work the same whether COOL is installed or not. The classes in a type restriction must be defined already, since they are used to predetermine the precedence between a generic function’s methods (see section 8.5.2 for more detail). Redundant classes are not allowed in restriction class lists. For example, the following method parameter’s type restriction is redundant since INTEGER is a subclass of NUMBER.

Example

(defmethod foo ((?a INTEGER NUMBER)))

 

If the type restriction (if any) is satisfied for an argument, then a query restriction (if any) will be applied. The query restriction must either be a global variable or a function call. CLIPS evaluates this expression, and if it evaluates to anything but the symbol FALSE, the restriction is considered satisfied. Since a query restriction is not always satisfied, queries should not have any side‑effects, for they will be evaluated for a method that may not end up being applicable to the generic function call. Since parameter restrictions are examined from left to right, queries which involve multiple parameters should be included with the rightmost parameter. This insures that all parameter type restrictions have already been satisfied. For example, the following method delays evaluation of the query restriction until the classes of both arguments have been verified.

Example

(defmethod foo ((?a INTEGER) (?b INTEGER (> ?a ?b))))

 

If the argument passes all these tests, it is deemed acceptable to a method. If all  generic function arguments are accepted by a method’s restrictions, the method itself is deemed applicable to the set of arguments. When more than one method is applicable to a set of arguments, the generic dispatch must determine an ordering among them and execute the first one in that ordering. Method precedence is used for this purpose and will be discussed in section 8.5.2.

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> (clear)

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 Parameter

A 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.

 

If multifield values are passed as extra arguments, they will all be merged into one multifield value referenced by the wildcard parameter. This is because CLIPS does not support nested multifield values.

 

Type and query restrictions can be applied to arguments grouped in the wildcard parameter similarly to regular parameters. Such restrictions apply to each individual field of the resulting multifield value (not the entire multifield). However, expressions involving the wildcard parameter variable may be used in the query. In addition, a special variable may be used in query restrictions on the wildcard parameter to refer to the individual arguments grouped into the wildcard: ?current‑argument. This variable is only in scope within the query and has no meaning in the body of the method. For example, to create a version of the ‘+’ operator which acts differently for sums of all even integers:

Example

CLIPS>

(defmethod +

  (($?any INTEGER (evenp ?current-argument)))

  (div (call-next-method) 2))

CLIPS> (+ 1 2)

3

CLIPS> (+ 4 6 4)

7

CLIPS>

 

It is important to emphasize that query and type restrictions on the wildcard parameter are applied to every argument grouped in the wildcard. Thus in the following example, the > and length$ functions are actually called three times, since there are three arguments:

Example

CLIPS> (defmethod foo (($?any (> (length$ ?any) 2))) yes)

CLIPS> (foo 1 red 3)

yes

CLIPS>

 

In addition, a query restriction will never be examined if there are no arguments in the wildcard parameter range. For example, the the previous methodwould be applicable to a call to the generic function with no arguments because the query restriction is never evaluated:

Example

CLIPS> (foo)

yes

CLIPS>

 

Typically query restrictions applied to the entire wildcard parameter are testing the cardinality (the number of arguments passed to the method). In cases like this where the type is irrelevant to the test, the query restriction can be attached to a regular parameter instead to improve performance (see section 8.5.1). Thus the previous method could be improved as follows:

Example

CLIPS> (clear)

CLIPS> (defmethod foo ((?arg (> (length$ ?any) 1)) $?any) yes)

CLIPS> (foo)

[GENRCEXE1] No applicable methods for foo.

FALSE

CLIPS>

 

This approach should not be used if the types of the arguments grouped by the wildcard must be verified prior to safely evaluating the query restriction.

8.5 Generic Dispatch

When 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:

 

 

 

The solid arrows indicate automatic control transfer by the generic dispatch.

 

The dashed arrows indicate control transfer that can only be accomplished by the use or lack of the use of call‑next‑method or override‑next‑method

8.5.1 Applicability of Methods Summary

An 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.

 

Method restrictions are examined from left to right. As soon as one restriction is not satisfied, the method is abandoned, and the rest of the restrictions (if any) are not examined.

 

When a standard CLIPS system function is overloaded, CLIPS forms an implicit method definition corresponding to that system function. This implicit method is derived from the argument restriction string for the external DefineFunction2 call defining that function to CLIPS (see the Advanced Programming Guide). This string can be accessed with the function get‑function‑restrictions. The specification of this implicit method can be examined with the list‑defmethods or get‑method‑restrictions functions. The method that CLIPS will form for a system function can be derived by the user from the BNF given in this document. For example,

 

(+ <number> <number>+)

 

would yield the following method for the ‘+’ function:

 

(defmethod + ((?first NUMBER) (?second NUMBER) ($?rest NUMBER))

...)

 

The method definition is used to determine the applicability and precedence of the system function to the generic function call.

 

The following system functions cannot be overloaded, and CLIPS will generate an error if an attempt is made to do so.

 

active‑duplicate‑instance

do‑for‑all‑instances

modify

active‑initialize‑instance

do‑for‑instance

modify‑instance

active‑make‑instance

duplicate

next‑handlerp

active‑message‑duplicate‑instance

duplicate‑instance

next‑methodp

active‑message‑modify‑instance

expand$

object‑pattern‑match‑delay

active‑modify‑instance

find‑all‑instances

override‑next‑handler

any‑instancep

find‑instance

override‑next‑method

assert

foreach

progn

bind

if

progn$

break

make‑instance

return

call‑next‑handler

initialize‑instance

switch

call‑next‑method

loop‑for‑count

while

call‑specific‑method

message‑duplicate‑instance

 

delayed‑do‑for‑all‑instances

message‑modify‑instance

 

8.5.2 Method Precedence

When 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).

 

The precedence between two methods is determined by comparing their parameter restrictions. In general, the method with the most specific parameter restrictions has the highest precedence. For example, a method which demands an integer for a particular argument will have higher precedence than a method which only demands a number. The exact rules of precedence between two methods are given in order below; the result of the first rule which establishes precedence is taken.

 

1) ) The parameter restrictions of both methods are positionally compared from left to right. In other words, the first parameter restriction in the first method is matched against the first parameter restriction in the second method, and so on. The comparisons between these pairs of parameter restrictions from the two methods determine the overall precedence between the two methods. The result of the first pair of parameter restrictions which specifies precedence is taken. The following rules are applied in order to a parameter pair; the result of the first rule which establishes precedence is taken.

 

1a) A regular parameter has precedence over a wildcard parameter.

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.

 

2) The method with the greater number of regular parameters has precedence.

 

3) A method without a wildcard parameter has precedence over one that does

 

4) A method defined before another one has priority.

 

If there are multiple classes on a single restriction, determining specificity is slightly more complicated. Since all precedence determination is done when the new method is defined, and the actual class of the generic function argument will not be known until run‑time, arbitrary (but deterministic) rules are needed for determining the precedence between two class lists. The two class lists are examined by pairs from left to right, e.g. the pair of first classes from both lists, the pair of second classes from both lists and so on. The first pair containing a class and its superclass specify precedence. The class list containing the subclass has priority. If no class pairs specify precedence, then the shorter class list has priority. Otherwise, the class lists do not specify precedence between the parameter restrictions.

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 NUMBER) (?b INTEGER)))              ; #2

(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

 

The precedence would be: #7,#8,#3,#4,#6,#2,#1,#5. The methods can be immediately partitioned into three groups of decreasing precedence according to their restrictions on the first parameter: A) methods which have a query restriction and a type restriction of INTEGER (#7,#8), B) methods which have a type restriction of INTEGER (#3,#4), and C) methods which have a type restriction of NUMBER (#1,#2,#5,#6). Group A has precedence over group B because parameters with query restrictions have priority over those that do not. Group B has precedence over group C because INTEGER is a subclass of NUMBER. Thus, the ordering so far is: (#7,#8),(#3,#4),(#1,#2,#5,#6). Ordering between the methods in a particular set of parentheses is not yet established.

 

The next step in determining precedence between these methods considers their restrictions on the second parameter. #7 has priority over #8 because INTEGER is a subclass of NUMBER. #3 has priority over #4 because INTEGER is a subclass of NUMBER. #6 and #2 have priority over #1 and #5 because INTEGER is a subclass of NUMBER. #6 has priority over #2 because it has a query restriction and #2 does not. Thus the ordering is now: #7,#8,#3,#4,#6,#2,(#1,#5).

 

The restriction on the wildcard argument yields that #1 (the system function implicit method) has priority over #5 since NUMBER is a sublclass of PRIMITIVE. This gives the final ordering: #7,#8,#3,#4,#6,#2,#1,#5.

Example 2

(defmethod foo ((?a NUMBER STRING)))         ; #1

(defmethod foo ((?a INTEGER LEXEME)))        ; #2

 

The precedence would be #2,#1. Although STRING is a subclass of LEXEME, the ordering is still #2,#1 because INTEGER is a subclass of NUMBER, and NUMBER/INTEGER is the leftmost pair in the class lists.

Example 3

(defmethod foo ((?a MULTIFIELD STRING)))     ; #1

(defmethod foo ((?a LEXEME)))                ; #2

 

The precedence would be #2,#1 because the classes of the first pair in the type restriction (MULTIFIELD/LEXEME) are unrelated and #2 has fewer classes in its class list.

Example 4

(defmethod foo ((?a INTEGER LEXEME)))        ; #1

(defmethod foo ((?a STRING NUMBER)))         ; #2

 

Both pairs of classes (INTEGER/STRING and LEXEME/NUMBER) are unrelated, and the class lists are of equal length. Thus, the precedence is taken from the order of definition: #1,#2.

8.5.3 Shadowed Methods

If 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 Errors

If 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 Value

The 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.

 

The return value of a particular method is the last action evaluated by that method.


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 Background

COOL 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 Classes

COOL 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.

 

All of these system classes except INITIAL‑OBJECT are abstract classes, which means that their only use is for inheritance (direct instances of this class are illegal). None of these classes have slots, and, except for the class USER, none of them have message‑handlers. However, the user may explicitly attach message‑handlers to all of the system classes except for INSTANCE, INSTANCE‑ADDRESS and INSTANCE‑NAME. The OBJECT class is a superclass of all other classes, including user‑defined classes. All user‑defined classes should (but are not required to) inherit directly or indirectly from the class USER, since this class has all of the standard system message‑handlers, such as initialization and deletion, attached to it. Section 9.4 describes these system message‑handlers.

 

The PRIMITIVE system class and all of its subclasses are provided mostly for use in generic function method restrictions, but message‑handlers and new subclasses may be attached if desired. However, the three primitive system classes INSTANCE, INSTANCE‑ADDRESS and INSTANCE‑NAME are provided strictly for use in methods (particularly in forming implicit methods for overloaded system functions - see section 8.5.1) and as such cannot have subclasses or message‑handlers attached to them.

 

The INITIAL‑OBJECT class is provided for use by the default definstances initial‑object in creating the default instance [initial‑object] during the reset command. This system class is concrete and reactive to pattern‑matching on the LHS of rules but is in other respects exactly like the system class USER. The instance [initial‑object] is for use by the initial‑object pattern (see section 5.4.9).

9.3 Defclass Construct

A 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.

 

Any slots explicitly given in the defclass override those gotten from inheritance. COOL applies rules to the list of superclasses to generate a class precedence list (see section 9.3.1) for the new class. Facets (see section 9.3.3) further describe slots. Some examples of facets include: default value, cardinality, and types of access allowed.

Syntax

Defaults are outlined.

 

(defclass <name> [<comment>]

  (is-a <superclass-name>+)

  [<role>]

  [<pattern-match-role>]

  <slot>*

  <handler-documentation>*)

 

<role>  ::= (role concrete | abstract)

 

<pattern-match-role>

        ::= (pattern-match reactive | non-reactive)

 

<slot>  ::= (slot <name> <facet>*) |

            (single-slot <name> <facet>*) |

            (multislot <name> <facet>*)

 

<facet> ::=  <default-facet> | <storage-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>*)

 

<storage-facet> ::= (storage local | shared)

 

<access-facet>

       ::= (access read-write | read-only | initialize-only)

 

<propagation-facet> ::= (propagation inherit | no-inherit)

 

<source-facet> ::= (source exclusive | composite)

 

<pattern-match-facet>

       ::= (pattern-match reactive | non-reactive)

 

<visibility-facet> ::= (visibility private | public)

 

<create-accessor-facet>

     ::= (create-accessor ?NONE | read | write | read-write)

 

<override-message-facet>

     ::= (override-message ?DEFAULT | <message-name>)

                                           

<handler-documentation>

       ::= (message-handler <name> [<handler-type>])

 

<handler-type> ::= primary | around | before | after

 

Redefining an existing class deletes the current subclasses and all associated message‑handlers. An error will occur if instances of the class or any of its subclasses exist.

9.3.1 Multiple Inheritance

If 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 the class 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 Rules

COOL 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:

 

1) A class has higher precedence than any of its superclasses.

2) A class specifies the precedence between its direct superclasses.

 

If more than one class precedence list would satisfy these rules, COOL chooses the one most similar to a strict preorder depth‑first traversal. This heuristic attempts to preserve “family trees” to the greatest extent possible. For example, if a child inherited genetic traits from a mother and father, and the mother and father each inherited traits from their parents, the child’s class precedence list would be: child mother maternal‑grandmother maternal‑grandfather father paternal‑grandmother paternal‑grandfather. There are other orderings which would satisfy the rules (such as child mother father paternal‑grandfather maternal‑grandmother paternal‑grandmother maternal‑grandfather), but COOL chooses the one which keeps the family trees together as much as possible.

Example 1

(defclass A (is-a USER))

 

Class A directly inherits information from the class USER. The class precedence list for A is: A USER OBJECT.

Example 2

(defclass B (is-a USER))

 

Class B directly inherits information from the class USER. The class precedence list for B is: B USER OBJECT.

Example 3

(defclass C (is-a A B))

 

Class C directly inherits information from the classes A and B. The class precedence list for C is: C A B USER OBJECT.

Example 4

(defclass D (is-a B A))

 

Class D directly inherits information from the classes B and A. The class precedence list for D is: D B A USER OBJECT.

Example 5

(defclass E (is-a A C))

 

By rule #2, A must precede C. However, C is a subclass of A and cannot succeed A in a precedence list without violating rule #1. Thus, this is an error.

Example 6

(defclass E (is-a C A))

 

Specifying that E inherits from A is extraneous, since C inherits from A. However, this definition does not violate any rules and is acceptable. The class precedence list for E is: E C A B USER OBJECT.

Example 7

(defclass F (is-a C B))

 

Specifying that F inherits from B is extraneous, since C inherits from B. The class precedence list for F is: F C A B USER OBJECT. The superclass list says B must follow C in F’s class precedence list but not that B must immediately follow C.

Example 8

(defclass G (is-a C D))

 

This is an error, for it violates rule #2. The class precedence of C says that A should precede B, but the class precedence list of D says the opposite.

Example 9

(defclass H (is-a A))

(defclass I (is-a B))

(defclass J (is-a H I A B))

 

The respective class precedence lists of H and I are: H A USER OBJECT and I B USER OBJECT. If J did not have A and B as direct superclasses, J could have one of three possible class precedence lists: J H A I B USER OBJECT, J H I A B USER OBJECT or J H I B A USER OBJECT. COOL would normally pick the first list since it preserves the family trees (H A and I B) to the greatest extent possible. However, since J inherits directly from A and B, rule #2 dictates that the class precedence list must be J H I A B USER OBJECT.

 

Usage Note

 

For most practical applications of multiple inheritance, the order in which the superclasses are specified should not matter. If you create a class using multiple inheritance and the order of the classes specified in the is-a attribute effects the behavior of the class, you should consider whether your program design is needlessly complex.

9.3.2 Class Specifiers

9.3.2.1 Abstract and Concrete Classes

An 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 Classes

Objects 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 Slots

Slots 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.

 

To determine the set of slots for an instance, the class precedence list for the instance’s class is examined in order from most specific to most general (left to right). A class is more specific than its superclasses. Slots specified in any of the classes in the class precedence list are given to the instance, with the exception of no‑inherit slots (see section 9.3.3.5). If a slot is inherited from more than one class, the definition given by the more specific class takes precedence, with the exception of composite slots (see section 9.3.3.6).

Example

(defclass A (is-a USER)

   (slot fooA)

   (slot barA))

 

(defclass B (is-a A)

   (slot fooB)

   (slot barB))

 

The class precedence list of A is: A USER OBJECT. Instances of A will have two slots: fooA and barA. The class precedence list of B is: B A USER OBJECT. Instances of B will have four slots: fooB, barB, fooA and barA.

 

Just as slots make up classes, facets make up slots. Facets describe various features of a slot that hold true for all objects which have the slot: default value, storage, access, inheritance propagation, source of other facets, pattern‑matching reactivity, visibility to subclass message‑handlers, the automatic creation of message‑handlers to access the slot, the name of the message to send to set the slot and constraint information. Each object can still have its own value for a slot, with the exception of shared slots (see section 9.3.3.3).

9.3.3.1 Slot Field Type

A 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 Facet

The 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).

 

The default facet is a static default: the specified expression is evaluated once when the class is defined, and the result is stored with the class. This result is assigned to the appropriate slot when a new instance is created. If the keyword ?DERIVE is used for the default value, then a default value is derived from the constraints for the slot (see section 11.5 for more details). By default, the default attribute for a slot is (default ?DERIVE). If the keyword ?NONE is used for the default value, then the slot is not assigned a default value. Using this keyword causes make‑instance to require a slot‑override for that slot when an instance is created. Note that in CLIPS 6.0, a slot now has a default even if one is not explicitly specified (unlike CLIPS 5.1). This could cause different behavior for CLIPS 5.1 programs using the initialize‑instance function. The ?NONE keyword can be used to recover the original behavior for classes.

 

The default‑dynamic facet is a dynamic default: the specified expression is evaluated every time an instance is created, and the result is assigned to the appropriate slot.

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 Facet

The 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.

 

A shared slot will always pick up a dynamic default value from a defclass when an instance is created or initialized, but the shared slot will ignore a static default value unless it does not currently have a value. Any changes to a shared slot will cause pattern‑matching for rules to be updated for all reactive instances containing 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 Facet

There 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 Facet

An 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 Facet

When 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)

===============================================================

***************************************************************

Concrete: direct instances of this class can be created.

Reactive: direct instances of this class can match defrule patterns.

 

Direct Superclasses: A

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

 

Constraint information for slots:

 

SLOTS : SYM STR INN INA EXA FTA INT FLT

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 Facet

Normally, 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 Facet

Normally, 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

 

[PRCCODE3] Undefined variable self:foo referenced in message-handler.

 

ERROR:

(defmessage-handler MAIN::B get-foo

   ()

   ?self:foo

   )

CLIPS>

9.3.3.9 Create‑Accessor Facet

The 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.

 

If the value ?NONE is specified for the facet, no message-handlers are created.

 

If the value read is specified for the facet, CLIPS creates the following message‑handler:

 

(defmessage-handler <class> get-<slot-name> primary ()

   ?self:<slot-name>)

 

If the value write is specified for the facet, CLIPS creates the following message‑handler for single‑field slots:

 

(defmessage-handler <class> put-<slot-name> primary (?value)

   (bind ?self:<slot-name> ?value)

 

or the following message‑handler for multifield slots:

 

(defmessage-handler <class> put-<slot-name> primary ($?value)

   (bind ?self:<slot-name> ?value)

 

If the value read‑write is specified for the facet, both the get‑ and one of the put‑ message‑handlers are created.

 

If accessors are required that do not use static slot references (see sections 9.4.2, 9.6.3 and 9.6.4), then user must define them explicitly with the defmessage‑handler construct.

 

The access facet affects the default value for the the create‑accessor facet. If the access facet is read-write, then the default value for the create-accessor facet is read-write. If the access facet is read-only, then the default value is read. If the access facet is initialize‑only, then the default is ?NONE.

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 Facet

There 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 Facets

The 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.

 

Regardless of whether static or dynamic checking is enabled, multifield values can never be stored in single‑field slots. Single‑field values are converted to a multifield value of length one when storing in a multifield slot. In addition, the evaluation of a function which has no return value is always illegal as a slot value.

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 Documentation

COOL 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 Construct

Objects 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:

 

Type

Role for the Class

primary

Performs the majority of the work for the message

before

Does auxiliary work for a message before the primary handler executes

after

Does auxiliary work for a message after the primary handler executes

around

Sets up an environment for the execution of the rest of the handlers

 

Before and after handlers are for side‑effects only; their return values are always ignored. Before handlers execute before the primary ones, and after message‑handlers execute after the primary ones. The return value of a message is generally given by the primary message‑handlers, but around handlers can also return a value. Around message‑handlers allow the user to wrap code around the rest of the handlers. They begin execution before the other handlers and pick up again after all the other message‑handlers have finished.

 

A primary handler provides the part of the message implementation which is most specific to an object, and thus the primary handler attached to the class closest to the immediate class of the object overrides other primary handlers. Before and after handlers provide the ability to pick up behavior from classes that are more general than the immediate class of the object, thus the message implementation uses all handlers of this type from all the classes of an object. When only the roles of the handlers specify which handlers get executed and in what order, the message is said to be declaratively implemented. However, some message implementations may not fit this model well. For example, the results of more than one primary handler may be needed. In cases like this, the handlers themselves must take part in deciding which handlers get executed and in what order. This is called the imperative technique. Around handlers provide imperative control over all other types of handlers except more specific around handlers. Around handlers can change the environment in which other handlers execute and modify the return value for the entire message. A message implementation should use the declarative technique if at all possible because this allows the handlers to be more independent and modular.

 

A defmessage‑handler is comprised of seven elements: 1) a class name to which to attach the handler (the class must have been previously defined), 2) a message name to which the handler will respond, 3) an optional type (the default is primary), 4) an optional comment, 5) a list of parameters that will be passed to the handler during execution, 6) an optional wildcard parameter and 7) a series of expressions which are executed in order when the handler is called. The return‑value of a message‑handler is the evaluation of the last expression in the body.

Syntax

Defaults are outlined.

 

(defmessage-handler <class-name> <message-name>

                   [<handler-type>] [<comment>]

   (<parameter>* [<wildcard-parameter>])

   <action>*)

 

<handler-type>          ::= around | before | primary | after

<parameter>                     ::= <single-field-variable>

<wildcard-parameter>    ::= <multifield-variable>

 

Message‑handlers are uniquely identified by class, name and type. Message‑handlers are never called directly. When the user sends a message to an object, CLIPS selects and orders the applicable message‑handlers attached to the object’s class(es) and then executes them. This process is termed the message dispatch.

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 Parameters

A 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.

 

Handler parameters have no bearing on the applicability of a handler to a particular message (see section 9.5.1). However, if the number of arguments is inappropriate, a message execution error (see section 9.5.4) will be generated when the handler is called. Thus, the number of arguments accepted should be consistent for all message‑handlers applicable to a particular message.

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 Parameter

The 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 Actions

The 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.

 

Handler actions may directly manipulate slots of the active instance. Normally, slots can only be manipulated by sending the object slot‑accessor messages (see sections 9.3.3.9 and 9.4.3). However, handlers are considered part of the encapsulation (see section 2.6.2) of an object, and thus can directly view and change the slots of the object. There are several functions which operate implicitly on the active instance (without the use of messages) and can only be called from within a message‑handler. These functions are discussed in section 12.16.

 

A shorthand notation is provided for accessing slots of the active instance from within a message‑handler.

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>

 

The bind function can also take advantage of this shorthand notation to set the value of a slot.

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>

 

Direct slot accesses are statically bound to the appropriate slot in the defclass when the message‑handler is defined. Care must be taken when these direct slot accesses can be executed as the result of a message sent to an instance of a subclass of the class to which the message‑handler is attached. If the subclass has redefined the slot, the direct slot access contained in the message‑handler attached to the superclass will fail.  That message‑handler accesses the slot in the superclass, not the subclass.

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>

 

In order for direct slot accesses in a superclass message‑handler to apply to new versions of the slot in subclasses, the dynamic‑put and dynamic‑get (see sections 12.16.4.10 and 12.16.4.11) must be used. However, the subclass slot must have public visibility for this to work (see section 9.3.3.8).

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 Daemons

Daemons 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‑handlers

CLIPS defines eight primary message‑handlers that are attached to the class USER. These handlers cannot be deleted or modified.

9.4.4.1 Instance Initialization

Syntax

(defmessage-handler USER init primary ())

 

This handler is responsible for initializing instances with class default values after creation. The make‑instance and initialize‑instance functions send the init message to an instance (see sections 9.6.1 and 9.6.2); the user should never send this message directly. This handler is implemented using the init‑slots function (see section 12.13). User‑defined init handlers should not prevent the system message‑handler from responding to an init message (see section 9.5.3).

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 Deletion

Syntax

(defmessage-handler USER delete primary ())

 

This handler is responsible for deleting an instance from the system. The user must directly send a delete message to an instance. User‑defined delete message‑handlers should not prevent the system message‑handler from responding to a delete message (see section 9.5.3). The handler returns the symbol TRUE if the instance was successfully deleted, otherwise it returns the symbol FALSE.

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 Display

Syntax

(defmessage-handler USER print primary ())

 

This handler prints out slots and their values for an instance.

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 Instance

Syntax

(defmessage-handler USER direct-modify primary

  (?slot-override-expressions))

 

This handler modifies the slots of an instance directly rather than using put- override messages to place the slot values. The slot‑override expressions are passed as an EXTERNAL_ADDRESS data object to the direct‑modify handler. This message is used by the functions modify‑instance and active‑modify‑instance.

Example

The following around message‑handler could be used to insure that all modify message slot‑overrides are handled using put- messages.

 

(defmessage-handler USER direct-modify around

   (?overrides)

   (send ?self message-modify ?overrides))

9.4.4.5 Modifying an Instance using Messages

Syntax

(defmessage-handler USER message-modify primary

  (?slot-override-expressions)

 

This handler modifies the slots of an instance using put‑ messages for each slot update. The slot‑override expressions are passed as an EXTERNAL_ADDRESS data object to the message‑modify handler. This message is used by the functions message‑modify‑instance and active‑message‑modify‑instance.

9.4.4.6 Directly Duplicating an Instance

Syntax

(defmessage-handler USER direct-duplicate primary

  (?new-instance-name ?slot-override-expressions))

 

 

This handler duplicates an instance without using put- messages to assign the slot‑overrides. Slot values from the original instance and slot overrides are directly copied. If the name of the new instance created matches a currently existing instance‑name, then the currently existing instance is deleted without use of a message. The slot‑override expressions are passed as an EXTERNAL_ADDRESS data object to the direct‑duplicate handler. This message is used by the functions duplicate‑instance and active‑duplicate‑instance.

Example

The following around message‑handler could be used to insure that all duplicate message slot‑overrides are handled using put- messages.

 

(defmessage-handler USER direct-duplicate around

   (?new-name ?overrides)

   (send ?self message-duplicate ?new-name ?overrides))

9.4.4.7 Duplicating an Instance using Messages

Syntax

(defmessage-handler USER message-duplicate primary

  (?new-instance-name ?slot-override-expressions)

 

This handler duplicates an instance using messages. Slot values from the original instance and slot overrides are copied using put‑ and get‑ messages. If the name of the new instance created matches a currently existing instance‑name, then the currently existing instance is deleted using a delete message. After creation, the new instance is sent a create message and then an init message. The slot‑override expressions are passed as an EXTERNAL_ADDRESS data object to the message‑duplicate handler. This message is used by the functions message‑duplicate‑instance and active‑message‑duplicate‑instance.

9.4.4.8 Instance Creation

Syntax

(defmessage-handler USER create primary ())

 

This handler is called after an instance is created , but before any slot initialization has occurred. The newly created instance is sent a create message. This handler performs no actions—It is provided so that instance creation can be detected by user-defined message-handlers. The handler returns the symbol TRUE if the instance was successfully created, otherwise it returns the symbol FALSE.

9.5 Message Dispatch

When 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:

 

 

 

 

 

 

 

The solid arrows indicate automatic control transfer by the message dispatch system.

 

The dashed arrows indicate control transfer that can only be accomplished by the use or lack of the use of call‑next‑handler (or override‑next‑handler).

9.5.1 Applicability of Message‑handlers

A 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 Precedence

The 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.

 

The order of execution is as follows: 1) around handlers begin execution from most specific to most general (each around handler must explicitly allow execution of other handlers), 2) before handlers execute (one after the other) from most specific to most general 3) primary handlers begin execution from most specific to most general (more specific primary handlers must explicitly allow execution of more general ones), 4) primary handlers finish execution from most general to most specific, 5) after handlers execute (one after the other) from most general to most specific and  6) around handlers finish execution from most general to most specific.

 

There must be at least one applicable primary handler for a message, or a message execution error will be generated (see section 9.5.4).

9.5.3 Shadowed Message‑handlers

When 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