Up | Next | Prev | PrevTail | Tail |

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

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

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

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

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

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

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

(plus 9 X)

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

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.

Up | Next | Prev | PrevTail | Front |