4.3 Property List Functions
A property list is used to associate an id with a set of entities; those entities are called flags if
their use associates a boolean value with the id, and properties if the id is to be associated with
an arbitrary attribute.
(put U:id IND:id PROP:any): any expr
The indicator IND with the property PROP is placed on the property list of
U. If the action of put occurs, the value of PROP is returned. If either U or
IND are not ids then a type mismatch error occurs.
⋆⋆⋆⋆⋆ An attempt was made to do PUT on ‘U', which is not
an identifier
The definition of a property will cause the previous definition to be lost.
(get U:id IND:id): any expr
Returns the property associated with indicator IND from the property list
of U. If U does not have indicator IND, nil is returned. Get returns nil if U
is not an id.
(deflist U:list IND:id): list expr
U is a list in which each element is a two-element list: (ID:id PROP:any).
Each id in U has the indicator IND with property PROP placed on its
property list by the function put function. The value of deflist is a list of the
first elements of each two-element list.
1 lisp> (deflist '((plus2 'two)
(plus 'many))
'no-operands)
(plus2 plus)
2 lisp> (get 'plus 'no-operands)
many
(remprop U:id IND:id): any expr
Removes the property with indicator IND from the property list of U.
Returns the removed property or nil if there was no such indicator.
(rempropl U:id-list IND:id): nil expr
Removes the property IND from all of the ids in U.
The following example is intended to illustrate the idea of data driven programming. We define a
function called simplify which will simplify symbolic algebraic expressions. These expressions
are represented as lists. To begin, there will be only one operator (plus), and operands may be
integers, variables or an application of plus. Prefix notation is used. The addition of variable x
and 3 would be represented as (plus x 3). The first version of simplify will certainly do the
job.
(de simplify (expression)
(cond ((atom expression) expression)
((eq (first expression 'plus)
(add-simplify expression))
(t expression)))
However, as we add operands it will become necessary to redefine simplify. A better
approach is to allow the operator to specify the information on how to simplify the
expression.
(de simplify (expression)
(cond ((atom expression) expression)
(t (apply (get (first expression) 'simplify)
(ncons expression)))))
(put 'plus 'simplify 'add-simplify)
This version will not have to be rewritten when a new operator is added. For example, if the
operator times is added then we only need to define a function called times-simplify and attach
its name to the property list of times under the indicator simplify. We can design add-simplify in
a similar fashion. Using this approach we will be able to accomodate numbers other than
integers.
(de add-simplify (expression)
(let ((left (second expression))
(right (third expression)))
(cond ((zerop left) right)
((zerop right) left)
((and (numberp left)(numberp right))
(let ((new (common-type left right)))
(apply (get (data-type (first new))'add-op) new)))
(t (list (first expression)
(simplify left)
(simplify right))))))
(put 'integer 'add-op 'plus2)
1 lisp> (simplify '(plus (plus 1 8) (plus x 0)))
(plus 9 X)
4.3.1 Functions for Flagging Ids
(flag U:id-list V:id): nil expr
Flag flags each id in U with V; that is, the effect of flag is that for each id X
in U, (flagp X V) has the value t. Both V and all of the elements of U must
be identifiers or a type mismatch error occurs. The id V will appear on the
property list of each id in U. However, flags cannot be accessed, placed on,
or removed from property lists using the normal property list functions get,
put, and remprop. Note that if an error occurs during execution of flag, then
some of the ids in U may be flagged with V, and others may not be. The
statement below causes the flag Lose to be placed on the property lists of
the ids x and y.
(flag '(x y) 'lose)
(flagp U:id V:id): boolean expr
Returns t if U has been flagged with V; otherwise returns nil. Returns NIL
if either U or V is not an id.
(remflag U:id-list V:id): nil expr
Removes the flag V from the property list of each member of the list U.
Both V and all the elements of U must be ids or the type mismatch error
occurs.
(flag1 U:id V:any): Undefined expr
The identifier U is flagged V. The effect is to add V to the property list of
U.
(remflag1 U:id V:any): Undefined expr
The identifier U is no longer flagged V. The effect is to removed V from the
property list of U.
4.3.2 Direct Access to the Property Cell
Use of the following functions can destroy the integrity of the property list. Since PSL uses
properties at a low level, care should be taken in the use of these functions.
(prop U:id): any expr
Returns the property list of U.
(setprop U:id L:any): L:any expr
Store item L as the property list of U.