As previously stated in the introduction, PyCLIPS provides classes and objects to access CLIPS ``entities''. It could be preferable to refer to counterparts ``living'' in the CLIPS subsystem as entities than as objects, because it is common practice in OOP to give the name of ``objects'' to class instances: since CLIPS has its own object oriented structure (in fact there are classes in CLIPS, and therefore also instances of these), calling these structures simply objects may generate confusion.
Entities in CLIPS are generated by constructs, one for each type
of entity. In Python, the common way to create something is to instance
an object for a certain class. So it seemed straightforward
to make a class for each of these entities, and to substitute the constructs
used in CLIPS to create entities with factory functions. These
functions are defined at module level, and have names of the type
BuildEntity() where Entity is the
type of entity that has to be created. The only exception for this are
Fact objects, which are created in several ways from
Templates or Assertions.
There is another way to create entities in the CLIPS subsystem, that is directly using the Build() function with a full CLIPS construct as string argument. However, this function does not return anything to the caller, so the created entity has to be sought after creation to obtain a reference.
The BuildEntity() functions and the Assert() function return objects of proper types (whose detailed list is given below) which shadow the corresponding entities in the CLIPS space.
Note: Many objects in PyCLIPS have common features3.1, such as a factory function as stated above, or methods returning their name or their so-called pretty-print form: in the following detailed documentation only the first occurrence of a feature will be described thoroughly.
There are some simple classes that deserve a special mention in the PyCLIPS module, used to represent in Python namespace the basic types in CLIPS. These wrappers are used to differentiate values that CLIPS returns from other values that live in the Python space. However these classes are equivalent to their Python counterparts, and there is no need to pass objects converted to these classes to the module functions. Here is a list containing the class names and their equivalents in Python:
| Class | Type | Python Equivalent |
|---|---|---|
| Integer | ClipsIntegerType | int |
| Float | ClipsFloatType | float |
| String | ClipsStringType | str |
| Symbol | ClipsSymbolType | str |
| InstanceName | ClipsInstanceNameType | str |
| Multifield | ClipsMultifieldType | list |
A special object named Nil is defined, and is equivalent to
Symbol('nil') in comparisons and slot assignments. It is provided
to make code more readable in such situations. It has to be noticed that
also Nil evaluates to False in boolean tests: this also
yields for the explicit Symbol('nil') and Symbol('FALSE')
definitions3.2.
Templates are used to build Fact objects, that is, they provide a systematic way to construct Facts sharing a common pattern, and the only way to define Facts that have named Slots (the equivalent of record fields or structure members in other programming languages).
This represents a copy of a deftemplate construct in the CLIPS
subsystem, and not a true deftemplate entity. More than one
Template object in Python can refer to the same
deftemplate entity in the CLIPS subsystem.
| ) |
| ) |
| ) |
| fact) |
| ) |
| ) |
slots information. This is itself an
object, having many methods, and deserves a special explaination.
| name) |
slot specified by name.
| name) |
slot specified by name.
| name) |
slot specified by name.
| name) |
slot specified by name exists,
False otherwise.
| name) |
?NONE, STATIC_DEFAULT when
the default value is static and DYNAMIC_DEFAULT when it
is dynamically generated (eg. gensym).
| name) |
slot specified by name is
a Multifield value, False otherwise.
| name) |
slot specified by name is
a single field value, False otherwise.
| ) |
slot names.
| name) |
slot specified by
name.
| name) |
slot specified by
name.
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Templates is BuildTemplate(), which has been discussed above.
Facts are one of the main entities in CLIPS, since it is whether a Fact exists or not of that drives the subsystem in the decision to fire or not certain Rules. Facts, as seen above, can be created in several ways, that is either by directly asserting sentences in string form, or by building them first from Templates and then asserting them.
This represents a copy of a fact definition in the CLIPS subsystem, and not a true fact entity. More than one Fact objects in Python can refer to the same fact entity in the CLIPS subsystem. Many CLIPS functions return a Fact object, but most Fact objects obtained from CLIPS are read-only3.5. Read-only Facts cannot be reasserted or modified in Slots, and are provided for ``informational'' purposes only.
The argument can be a string with the same format of the Assert() function seen in the previous chapter: in this case the fact is created and asserted. Otherwise the argument can be a Template object, and in this case the resulting Fact can be modified and then asserted via the Assert() member function.
| ) |
| ) |
| ) |
| ) |
| ) |
| [ignoredefaults]) |
| ) |
slots are accessible using a dict-like syntax (square
brackets), but not all the members of dict are implemented.
Please note that Facts have slightly different methods than classes representing other entities in CLIPS: an instance of Fact is created using the module-level Assert() function, and removed using the Retract() member function: this syntax, closer to the original CLIPS form, was seen as the preferred method instead of using a name such as BuildFact() for creation and a Remove() member because of the particular nature of Fact related to other types of entity.
Here is an example of usage of Fact and Template objects:
>>> import clips
>>> clips.Reset()
>>> t0 = clips.BuildTemplate("person", """
(slot name (type STRING))
(slot age (type INTEGER))
""", "template for a person")
>>> print t0.PPForm()
(deftemplate MAIN::person "template for a person"
(slot name (type STRING))
(slot age (type INTEGER)))
>>> f1 = clips.Fact(t0)
>>> f1_slotkeys = f1.Slots.keys()
>>> print f1_slotkeys
<Multifield [<Symbol 'name'>, <Symbol 'age'>]>
>>> f1.Slots['name'] = "Grace"
>>> f1.Slots['age'] = 24
>>> print f1.PPForm()
f-0 (person (name "Grace") (age 24))
>>> clips.PrintFacts()
f-0 (initial-fact)
>>> f1.Assert()
<Fact 'f-1': fact object at 0x00E0CB10>
>>> print f1.Exists()
True
>>> clips.PrintFacts()
f-0 (initial-fact)
f-1 (person (name "Grace") (age 24))
For a total of 2 facts.
>>> f1.Retract()
>>> print f1.Exists()
False
>>> clips.PrintFacts()
f-0 (initial-fact)
For a total of 1 fact.
Please note that slot names are implemented as Symbols, and the list of Slots is returned as a Multifield. Also note that the Fact f1, that has been constructed from a Template (and not yet Asserted) object and then modified using the Slots property, can be Asserted while other Facts built from construct strings cannot.
A Deffacts is used to modify the ``initial structure'' of a CLIPS environment, by allowing some Facts to be Asserted by default each time the Reset() function is called.
This represents a copy of a deffacts construct in the CLIPS
subsystem, and not a true deffacts entity. More than one
Deffacts object in Python can refer to the same deffacts
entity in the CLIPS subsystem.
| ) |
| ) |
| ) |
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Deffacts is BuildDeffacts(), which has been discussed above.
The construct defines rules to be activated and then fired whenever
particular conditions are met. This construct is in fact the counterpart
of the defrule construct in CLIPS. Normally conditions that fire
Rules are Facts Asserted during a session.
This represents a copy of a defrule construct in the CLIPS
subsystem, and not a true defrule entity. More than one
Rule object in Python can refer to the same defrule
entity in the CLIPS subsystem.
| ) |
| ) |
| ) |
| ) |
| ) |
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Rules is BuildRule(), which has been discussed above.
An example - derived from the ones present in the standard CLIPS documentation - may be useful here:
>>> clips.Reset()
>>> r1 = clips.BuildRule("duck-rule", "(duck)",
"(assert (quack))", "The Duck rule")
>>> print r1.PPForm()
(defrule MAIN::duck-rule "The Duck rule"
(duck)
=>
(assert (quack)))
>>> clips.PrintFacts()
f-0 (initial-fact)
For a total of 1 fact.
>>> clips.PrintRules()
MAIN:
duck-rule
>>> f1 = clips.Assert("(duck)")
>>> clips.PrintAgenda()
MAIN:
0 duck-rule: f-1
For a total of 1 activation.
>>> clips.PrintFacts()
f-0 (initial-fact)
f-1 (duck)
For a total of 2 facts.
>>> clips.Run()
>>> clips.PrintFacts()
f-0 (initial-fact)
f-1 (duck)
f-2 (quack)
For a total of 3 facts.
Rule Activations are only returned by the CLIPS subsystem, and cannot be created - thus there is no factory function for these objects. CLIPS provides Activation objects to keep the program flow under control.
This represents a copy of an activation object in the CLIPS
subsystem, and not a true activation entity. More than one
Activation object in Python can refer to the same
activation entity in the CLIPS subsystem.
| ) |
| ) |
| ) |
The name of this entity in CLIPS is also returned by the string coercion function.
Global objects represent global variables in CLIPS, which
are normally built using the defglobal construct. To define a new
Global variable the BuildGlobal() function must be
used, which returns a new object.
A Global object represents a copy of a defglobal construct
in the CLIPS subsystem, and not a true defglobal entity. More
than one Global object in Python can refer to the same
defglobal entity in the CLIPS subsystem.
| ) |
| ) |
| ) |
| ) |
Some examples follow to show the use of Global objects:
>>> g_x = clips.BuildGlobal("x", 15)
This is equivalent to the CLIPS declaration:
CLIPS> (defglobal ?*x* = 15)
Some of the Global methods are illustrated here:
>>> g_x <Global 'x': defglobal object at 0x00E09960> >>> print g_x x >>> g_x.Value <Integer 15> >>> print g_x.Value 15 >>> print g_x.ValueForm() ?*x* = 15
The name of this entity in CLIPS is also returned by the string coercion function.
Objects of this type represent newly defined functions
(usually via the CLIPS deffunction construct) in the CLIPS
subsystem. In fact the BuildFunction() function described
above, which returns a Function object, corresponds to the
deffunction construct.
This represents a copy of a deffunction construct in the CLIPS
subsystem, and not a true deffunction entity. More than one
Function object in Python can refer to the same
deffunction entity in the CLIPS subsystem.
| [*args]) |
| ) |
| ) |
| ) |
The name of this entity in CLIPS is also returned by the string coercion function.
Note:
Objects of this class are callable themselves using the
syntax object([arg1 [, ... [argN]]), where the arguments follow
the same rules as in the Call method.
Generics (in CLIPS called generic functions) are similar to Functions, but they add generic programming capabilities to the CLIPS system. Python programmers will find them similar to Python functions, since overloading is possible within the corresponding construct.
Each different implementation (for different argument sets) of a
generic function is called a Method, and the Generic
class provides several ways to inspect the various Methods.
Methods are identified by an index.
This represents a copy of a defgeneric construct in the CLIPS
subsystem, and not a true defgeneric entity. More than one
Generic objects in Python can refer to the same
defgeneric entity in the CLIPS subsystem.
| restrictions, actions[, midx[, comment]]) |
Method to this Generic. The structure of this
function resembles the one of the Build<entity>() functions:
in fact this method of Generic actually implements the
defmethod construct which is present in CLIPS. For proper
documentation of this construct, see the CLIPS reference: the
restrictions parameter (which represents the Method
parameter restrictions) must be expressed without
parentheses; the actions parameter must be expressed as in the
defmethod construct, that is with all the necessary parentheses
pairs. midx is the Method index when it has to be forced
(optionally). The example below should be explanatory. restrictions
can also be expressed as a sequence of tuples, in each of which the
first element is the argument name (with its proper prefix) as a string
and the following ones are the actual restrictions, either in string form
or as CLIPS primitive types - which can be specified using PyCLIPS
wrapper classes types, see above.
| [*args]) |
| ) |
Method in this Generic.
| midx) |
Method can be deleted from this
Generic.
| midx) |
Method restrictions.
| ) |
Method indices for this Generic.
| midx) |
Method.
| midx) |
Method in this
Generic object: the midx parameter must be an
Integer or int indicating the Method index.
| midx) |
Method is being watched.
| midx) |
Method in this Generic given
the start index as an Integer or int.
| ) |
| ) |
Method list for this Generic.
| ) |
| midx) |
Method from this Generic.
| midx) |
Method.
| midx) |
Method.
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Generics is BuildGeneric(), which has been discussed above.
Note:
Objects of this class are callable themselves using the
syntax object([arg1 [, ... [argN]]), where the arguments follow
the same rules as in the Call method.
An example for this class follows.
>>> import clips
>>> addf = clips.BuildGeneric("my-addf", "my generic add function")
>>> addf.AddMethod("(?a STRING)(?b STRING)", "(str-cat ?a ?b)")
>>> addf.AddMethod("(?a INTEGER)(?b INTEGER)", "(+ ?a ?b)")
>>> addf.PrintMethods()
my-addf #1 (STRING) (STRING)
my-addf #2 (INTEGER) (INTEGER)
For a total of 2 methods.
>>> print addf.MethodPPForm(1)
(defmethod MAIN::my-addf
((?a STRING)
(?b STRING))
(str-cat ?a ?b))
>>> print addf.PPForm()
(defgeneric MAIN::my-addf "my generic add function")
>>> print clips.Eval('(my-addf 5 13)')
18
>>> print clips.Eval('(my-addf "hello,"(my-addf " " "world!"))')
hello, world!
>>> print clips.Eval('(my-addf "hello" 13)')
Traceback (most recent call last):
File "<pyshell#14>", line 1, in ?
print clips.Eval('(my-addf "hello" 13)')
File ".../_clips_wrap.py", line 2472, in Eval
return _cl2py(_c.eval(expr))
ClipsError: C10: unable to evaluate expression
>>> s = clips.ErrorStream.Read()
>>> print s
[GENRCEXE1] No applicable methods for my-addf.
Please note how the error stream (ErrorStream) can be used to retrieve a more explanatory text for the error. The error stream can be very useful during interactive debugging PyCLIPS sessions to fix errors.
Class objects are class definition constructs, the most
important feature of the COOL3.10 sublanguage of CLIPS. As in other OOP
environments, classes represent in CLIPS new data types (often
resulting from aggregation of simpler data types) which have particular ways
of being handled. Normally, as in Python, these particular ways are called
methods3.11, while in CLIPS they are called message handlers,
since to apply a method to a CLIPS object (in fact, the Instance
of a Class in PyCLIPS) a message has to be sent to that
object.
This represents a copy of a defclass construct in the CLIPS
subsystem, and not a true defclass entity. More than one
Class object in Python can refer to the same defclass
entity in the CLIPS subsystem.
| name, args, text [, type, comment]) |
| ) |
MessageHandler constructs of this Class
including the ones that have been inherited from the superclass.
| name, [overrides]) |
slots. If no slot is specified
to be overridden, then the Instance will assume default values.
| name, text [, comment]) |
| ) |
| ) |
| ) |
| o) |
| o) |
| index) |
MessageHandler can be deleted.
| name [, htype]) |
MessageHandler, given its name and type
(as the parameter htype). If type is omitted, it is considered to
be PRIMARY.
| index) |
MessageHandler.
| ) |
MessageHandler constructs for this
Class.
| index) |
MessageHandler.
| index) |
MessageHandler specified by the provided
index.
| index) |
MessageHandler.
| ) |
classes.
None is returned at the end of the list.
| instance) |
| index) |
MessageHandler with respect to the specified
one.
| instance) |
| ) |
| msgname) |
MessageHandlers suitable for specified message.
| ) |
MessageHandlers for this Class
including the ones that have been inherited from the superclass.
| ) |
MessageHandlers for this Class.
| name) |
| ) |
| index) |
MessageHandler specified by the provided index.
slots information. This is itself an object, having
many methods, and deserves a special explaination.
| name) |
slot specified by
name.
| name) |
slot specified by name.
| name) |
slot specified by name.
| name) |
slot specified by name.
| name) |
slot specified by name exists,
False otherwise.
| name) |
slot specified by name is defined
in this Class, False otherwise.
| name) |
slot specified by name.
| name) |
slot specified by name is directly
accessible, False otherwise.
| name) |
slot specified by name is
initializable, False otherwise.
| name) |
slot specified by name is
public, False otherwise.
| name) |
slot specified by name is
writable, False otherwise.
| ) |
slot names.
| ) |
slot names explicitly defined in this
Class.
| name) |
slot specified by
name.
| name) |
slot specified by name.
| name) |
slot specified by
name.
| ) |
| ) |
| index) |
MessageHandler.
| index) |
MessageHandler.
Slot debug status.
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Classes is BuildClass(), which has been discussed above.
Instance objects represent class instances (that is,
objects in the OOP paradigm) that live in the CLIPS subsystem.
Messages can be sent to those objects and values can be set and retrieved
for the slots defined in the related class, where the
meaning of slot has been described in the section above.
This represents a copy of an instance object in the CLIPS
subsystem, and not a true instance entity. More than one
Instance object in Python can refer to the same instance
entity in the CLIPS subsystem.
| ) |
| slotname) |
Slot specified as argument. The synonym
SlotValue is retained for readability and compatibility.
Please notice that these functions are provided in order to be more
coherent with the behaviour of CLIPS API, as CLIPS C interface users
know that a function like GetSlot usually bypasses message
passing, thus accessing slots directly. The possibilities
offered by GetSlot are also accessible using the Slots
property described below.
| ) |
| ) |
instances.
It returns None if there are no Instances left.
| ) |
| slotname, value) |
slot. The value parameter should
contain a value of the correct type, if necessary cast to one of the
wrapper classes described above if the type could be ambiguous.
The synonym SetSlotValue is provided for readability and
compatibility. What has been said about GetSlot also yields
for the hereby described function, as the possibilities offered by
PutSlot are also accessible using the Slots property
described below.
| ) |
| msg [, args]) |
slots. This member behaves
like a dict, but is not related to such objects. In fact, the
values of slots are accessible using a dict-like syntax
(square brackets), but not all the members of dict are
implemented. The functionality of PutSlot and
GetSlot is superseded by this property.
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Instances is BuildInstance(), which has been discussed above.
Here is an example of usage of Instance and Class objects:
>>> import clips
>>> clips.Build("""(defclass TEST1
(is-a USER)
(slot ts1 (type INSTANCE-NAME))
(multislot ts2))""")
>>> c = clips.FindClass("TEST1")
>>> print c.PPForm()
(defclass MAIN::TEST1
(is-a USER)
(slot ts1
(type INSTANCE-NAME))
(multislot ts2))
>>> clips.Reset()
>>> i = clips.BuildInstance("test1", c)
>>> i.Slots['ts2'] = clips.Multifield(['hi', 'there'])
>>> i.Slots['ts1'] = i.Name
>>> print i.PPForm()
[test1] of TEST1 (ts1 [test1]) (ts2 "hi" "there")
As there are deffacts for fact objects, instances
are supported in CLIPS by the definstances construct: it allows
certain default Instances to be created each time a
Reset() is issued. In PyCLIPS this construct is provided
via the Definstances class.
This represents a copy of the definstances construct in the CLIPS
subsystem, and not a true definstances entity. More than one
Definstances object in Python can refer to the same
definstances entity in the CLIPS subsystem.
| ) |
definstances. None is returned at the end of the list.
| ) |
| ) |
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Definstances is BuildDefinstances(), which has been discussed above.
Modules are a way, in CLIPS, to organize constructs, facts and
objects. There is a big difference between modules and
environments3.12: one should think of a
Module as a group of definitions and objects, which can
interoperate with entities that are defined in other Modules. The
Module class provides methods, similar to the ones defined at top
level, to directly create entities as part of the Module itself,
as well as methods to examine Module contents. Also,
Module objects have methods that instruct the related CLIPS
module to become current, so that certain operations can
be performed without specifying the module to which they have to
be applied.
This represents a copy of a defmodule construct in the CLIPS
subsystem, and not a true defmodule entity. More than one
Module object in Python can refer to the same defmodule
entity in the CLIPS subsystem.
| ) |
modules.
None is returned at the end of the list.
| ) |
| ) |
module that this object refers the current Module.
| ) |
For the following methods:
TemplateList(), FactList(), DeffactsList(), ClassList(), DefinstancesList(), GenericList(), FunctionList(), GlobalList(), BuildTemplate(), BuildDeffacts(), BuildClass(), BuildDefinstances(), BuildGeneric(), BuildFunction(), BuildGlobal(), BuildRule(), BuildInstance(), PrintTemplates(), PrintDeffacts(), PrintRules(), PrintClasses(), PrintInstances(), PrintSubclassInstances(), PrintDefinstances(), PrintGenerics(), PrintFunctions(), PrintGlobals(), ShowGlobals(), PrintAgenda(), PrintBreakpoints(), ReorderAgenda(), RefreshAgenda()
please refer to the corresponding function defined at module level, keeping in mind that these methods perform the same task but within the Module where they are executed.
The name of this entity in CLIPS is also returned by the string coercion function. The factory function for Modules is BuildModule(), which has been discussed above.
This class represents an environment, and implements almost all the module level functions and classes. The only objects appearing at PyCLIPS level and not at Environment level are the CLIPS I/O subsystem streams, which are shared with the rest of the CLIPS engine.
Environment objects are not a feature of CLIPS sessions (as stated above), thus there is no way to identify them in CLIPS using a symbol. So Environment objects do not have a Name property. Instead, CLIPS provides a way to identify an environment through an integer called index.
Please refer to top level functions, variables and classes for information on contents of Environment objects. The extra methods and properties follow below.
| ) |
Further explanations about Environment objects can be found in the appendices.
As seen in the introduction, there are a couple of objects that can be accessed to configure the underlying CLIPS engine and to retrieve its status. These are the EngineConfig and DebugConfig objects. The reason why configuration and status functions have been grouped in these objects is only cosmetic: in fact there is no counterpart of EngineConfig and DebugConfig in CLIPS. It was seen as convenient to group configuration and debug functions in two main objects and to make them accessible mainly as properties in Python, instead of populating the module namespace with too many get/set functions.
There is also an object, called Memory, which gives information about memory utilization and allow the user to attempt to free memory used by the CLIPS engine and no longer needed.
A description of what the above objects (which can not be instanced by the user of PyCLIPS3.13) actually expose follows.
The EngineConfig object allows the configuration of some features of the underlying CLIPS engine. Here are the properies provided by EngineConfig:
get/set-auto-float-dividend. When
True the dividend is always considered to be a floating point
number within divisions.
get/set-class-defaults-mode.
Possible values of this flag are CONVENIENCE_MODE and
CONSERVATION_MODE. See Clips Reference Guide Vol. II:
Advanced Programming Guide for details.
get/set-dynamic-constraint-checking.
When True, function calls and constructs are
checked against constraint violations.
get/set-fact-duplication. When
True, facts can be reasserted when they have already
been asserted3.14.
get/set-incremental-reset. When
True newly defined rules are updated according to
current facts, otherwise new rules will only be updated by
facts defined after their construction.
get/set-reset-globals. When
True the Global variables are reset to their initial
value after a call to Reset().
get/set-salience-evaluation. Can
be one of WHEN_DEFINED, WHEN_ACTIVATED,
EVERY_CYCLE. See the previous chapter and Clips Reference Guide Vol. II:
Advanced Programming Guide for
more information.
get/set-sequence-operator-recognition. When False,
Multifield values in function calls are treated as a single
argument.
get/set-static-constraint-checking.
When True, slot values are checked against constraint
violations.
get/set-strategy behaviour. Can be any of the following
values: RANDOM_STRATEGY, LEX_STRATEGY,
MEA_STRATEGY, COMPLEXITY_STRATEGY,
SIMPLICITY_STRATEGY, BREADTH_STRATEGY or
DEPTH_STRATEGY. See the previous chapter and Clips Reference Guide Vol. II:
Advanced Programming Guide for
more information.
The DebugConfig object provides access to the debugging and trace
features of CLIPS. During a CLIPS interactive session debug and trace
messages are printed on the system console (which maps the wtrace
I/O router). Users of the trace systems will have to poll the
TraceStream to read the generated messages.
In CLIPS, the process of enabling trace features on some class of entities is called to watch such a class; this naming convention is reflected in PyCLIPS. Note that specific objects can be watched: many classes have their own Watch property to enable or disable debugging on a particular object.
Also, CLIPS provides a facility to log all debug information to physical files: this is called to dribble on a file. Dribbling is possible from DebugConfig via the appropriate methods.
The names of methods and properties provided by this object are quite similar to the corresponding commands in CLIPS, so more information about debugging features can be found in Clips Reference Guide Vol. I: Basic Programming Guide.
| ) |
| ) |
| fn) |
Methods
within Generic functions.
MessageHandlers.
Slots.
facts
and instances, and other information after Run() has
been performed.
| ) |
| ) |
Note: Other CLIPS I/O streams besides TraceStream can be involved in the trace process: please refer to the CLIPS guides for details.
This object provides access to the memory management utilities of the underlying CLIPS engine. As said above, it allows the reporting of memory usage and the attempt to free memory that is used not for computational purposes. Also, a property of this object affects the engine behaviour about whether or not to cache some information. Here is what the object exposes:
| ) |
In order to be more embeddable, CLIPS defines a clear way to redirect its
messages to locations where they can be easily retrieved. CLIPS users can
access these locations for reading or writing by specifying them as
logical names (namely stdin, stdout, wtrace,
werror, wwarning, wdialog, wdisplay,
wprompt)3.15. PyCLIPS creates some special unique
objects3.16, called I/O streams throughout this
document, to allow the user to read messages provided by the underlying
engine. Most of these objects have only one method, called Read(),
that consumes CLIPS output and returns it as a string: this string contains
all output since a previous call or module initialization. The only exception
is StdinStream whose single method is Write() and it
accepts a string3.17 as parameter. As
CLIPS writes line-by-line, the string resulting from a call to
Read() can contain newline characters, often indicating
subsequent messages.
Here is a list of the I/O streams provided by PyCLIPS, along with a brief description of each.
| Stream | Description |
|---|---|
| StdoutStream | where information is usually printed out
(eg. via (printout t ...)) |
| TraceStream | where trace information (see watch) goes |
| ErrorStream | where CLIPS error messages are written in readable form |
| WarningStream | where CLIPS warning messages are written in readable form |
| DialogStream | where CLIPS informational messages are written in readable form |
| DisplayStream | where CLIPS displays information (eg.
the output of the (facts) command) |
| PromptStream | where the CLIPS prompt (normally
CLIPS>) is sent |
| StdinStream | where information is usually read by CLIPS
(eg. via (readline)) |
Some of the provided I/O streams are actually not so relevant for PyCLIPS programmers: for instance, it is of little use to read the contents of PromptStream and DisplayStream. In the latter case, in fact, there are other inspection functions that provide the same information in a more structured way than text. However they are available to provide a closer representation of the programming interface and allow CLIPS programmers to verify if the output of CLIPS-oriented calls (see the paragraph about Build() and Eval() in the appendices) really do what they are expected to.
PyCLIPS defines3.18, some Class objects, that is the ones that are present in CLIPS itself by default. They are defined in order to provide a compact access to CLIPS ``stock'' classes: most of these objects are of little or no use generally (although they can be handy when testing for class specification or generalization), but at least one (USER_CLASS) can be used to make code more readable.
Namely, these Classes are:
| Python Name | CLIPS defclass |
|---|---|
| FLOAT_CLASS | FLOAT |
| INTEGER_CLASS | INTEGER |
| SYMBOL_CLASS | SYMBOL |
| STRING_CLASS | STRING |
| MULTIFIELD_CLASS | MULTIFIELD |
| EXTERNAL_ADDRESS_CLASS | EXTERNAL-ADDRESS |
| FACT_ADDRESS_CLASS | FACT-ADDRESS |
| INSTANCE_ADDRESS_CLASS | INSTANCE-ADDRESS |
| INSTANCE_NAME_CLASS | INSTANCE-NAME |
| OBJECT_CLASS | OBJECT |
| PRIMITIVE_CLASS | PRIMITIVE |
| NUMBER_CLASS | NUMBER |
| LEXEME_CLASS | LEXEME |
| ADDRESS_CLASS | ADDRESS |
| INSTANCE_CLASS | INSTANCE |
| INITIAL_OBJECT_CLASS | INITIAL-OBJECT |
| USER_CLASS | USER |
The following code, shows how to use the ``traditional'' BuildClass() factory function and how to directly subclass one of the predefined Class object. In the latter case, probably, the action of subclassing is expressed in a more clear way:
>>> import clips
>>> C = clips.BuildClass("C", "(is-a USER)(slot s)")
>>> print C.PPForm()
(defclass MAIN::C
(is-a USER)
(slot s))
>>> D = clips.USER_CLASS.BuildSubclass("D", "(slot s)")
>>> print D.PPForm()
(defclass MAIN::D
(is-a USER)
(slot s))
Although it actually does not save typing (the statement is slightly longer), the second form can be used to produce more readable Python code.
Note:
These objects are actually useful only when the package is
fully imported, that is using the import clips form: importing
the symbols at global level (in the form from clips import *) does
in fact create some namespace problems. Since in the latter case the names
that represent stock classes are only references to the ones defined at
module level, PyCLIPS cannot change them when the actual classes are
relocated in the CLIPS memory space, for instance when Clear
is called.
fact entities
are read-only.
deftemplate for this kind of
Fact. However, once a Template with the specified slots
has been created, this becomes possible.
rule in CLIPS.
Method has been used
for function overloading in the definition of Generic
functions.
facts that would be asserted through firing of rules and would
generate duplications will not raise an error when this behaviour is
set.
t as a logical
name: as stated in Clips Reference Guide Vol. II:
Advanced Programming Guide this indicates stdin in functions
that read text and stdout in function that print out. In
PyCLIPS, for all functions that print out to t the user must
read from StdoutStream.
temporary, which is used internally to retrieve output from CLIPS
that shouldn't go anywhere else. PyCLIPS users however are not supposed
to interact with this object.