LISP in KID   

<<< Kernel Interface Driver (KID) - an Overview Chapters Object-Oriented KID >>>

Contents

[back to top]


2.1 Introduction

As previously discussed in the opening chapter we have assumed that users of KID have knowledge of LISP, but for those who are a little rusty or unsure of the concepts used, the following section is designed to get you started.

[back to top]

2.1.1 LISP evaluation

You should think of LISP as an interpreter. It evaluates or attempts to evaluate messages which you pass to it. The messages which you pass are called symbolic expressions (s-expressions).

S-expressions

In the following examples of s-expressions notice that numbers evaluate to themselves:

 

> ( times 3 4 )
12
> 3.1417
3.1417
> ( times 3 ( plus 2 2 ) )
12

S-expressions are composed of lists and atoms.

Atoms

Atoms are entities which LISP treats as whole items, i.e. they cannot be broken down further. Examples are:

Lists

Lists are chains of elements bounded by parentheses, where elements are either atoms or lists themselves. For example:

 

(3 4 5 )
(a d f )
( plus 2 ( times 4 3 ) )
( )			--- empty list

List evaluation

When evaluating lists LISP applies the following criteria:

 

> ( plus 2 4 )

 

> ( times 6 ( plus 1 ( plus 2 2 ) ) )
30

Quotation

S-expressions which are preceded by a quote ( ' ) are NOT evaluated, for example:

 

> ´ ( 3 4 )
( 3 4 )

> ( quote ( 3 4 ) )		--- is equivalent to the above
( 3 4 )
> ´a
a

[back to top]

2.1.2 Atomic Symbols

SETQ

As previously discussed, strings can be used as variables. They can be bound to values using the setq operator, for example:

 

> ( setq a 3 )
3
> a			--- `a´ now evaluates to 3
3
> ( setq a ( add1 a ) )
4
> a
4

A side effect of these type of operations is that the complete s-expression always evaluates to a result.

The following examples are equivalent forms:

 

> ( setq a 2 )

> ( set ´a 2 )

> ( set ( quote a ) 2 )

Predefined symbol-strings

A number of symbol-strings are predefined by the system, for example:

[back to top]


2.2 List operators

Symbolic operations on lists consist primarily of taking lists apart and building them up. LISP provides two basic functions for taking lists apart, these are car and cdr . Both are functions of one argument, which should be a list, and they always cause their argument to be evaluated.

[back to top]

2.2.1 CAR and CDR

car

car returns the first element of this list, for example:

 

> (car ´(a b c))
a

cdr

cdr returns the list with its first element missing, for example:

 

> (cdr ´(a b c))
(b c)

car and cdr are considered non-destructive as they do not actually change the lists on which they operate, for example:

 

> ( setq x ´(a b c))
(a b c)
> x
(a b c)
> (car x)
a
> x
(a b c)
> (cdr x)
(b c)
> x
(a b c)

Embedded car and cdr calls

car and cdr can be embedded in a single call, for example:

 

> (cdr (car ´((a b c) (d e f)))
(b c)
> (car (cdr ´((a b c) (d e f)))
(d e f)
> (car (cdr (car (cdr ´((a b c) (d e f))))))
e

Code containing long strings of cars and cdrs is hard to follow. Alternatively, the same calls can be made by the single function that corresponds to the sequence of calls used. For example, the previous examples would use these single calls to achieve the same results:

 

> (cdar ´((a b c) (d e f)))
(b c)
> (cadr ´((a b c) (d e f)))
(d e f)
> (cadadr ´((a b c) (d e f)))
e

element

The function element is a shorthand for embedded car and cdr calls, for example, in the following example element returns the third element of the given list:

 

> ( setq x ´(1 4 6 7 ) )
(1 4 6 7)
> ( element 3 x )
6

[back to top]

2.2.2 CONS

Just as car and cdr take lists apart, cons builds lists up. cons is a function of two arguments where the second argument should always evaluate to a list.

cons evaluates both of its arguments, and then returns as its value the list obtained by taking the second argument and placing the first one in front of it, for example:

 

> (cons ´a ´(b c))
(a b c)

cons can be considered to be the inverse function of car and cdr , as cons always produces a list whose car is the first argument to cons , and whose cdr is the second argument.

Like car and cdr , cons is non-destructive.

Dotted pairs

If the second argument to cons is an atom then the result is a dotted pair rather than a list. In most cases this is not a desirable result and the use of list would produce preferable results. However, the syntax for the input of PK option structures requires the use of dotted pairs for which cons should be used. For example:

 

(cons ´a ´b) -> (a . b)
(cons ´a ´(b c)) -> (a b c)
(cons ´(a b) ´c) -> ((a b) . c)
(list ´(a b) ´c) -> ((a b) c)

[back to top]

2.2.3 LIST and APPEND

cons can be used to build up complicated s-expressions, for example, to create the lists (1 2 3) and (a (b c) d), using cons we would:

 

> (cons ´1 (cons ´2 (cons ´3 nil)))
(1 2 3)
> (cons ´a (cons (cons ´b (cons ´c nil)) (cons ´d nil)))
(a (b c) d)

As this is obviously cumbersome, the list and append functions are simpler ways to build new lists.

list

list takes any number of arguments, evaluates them, and builds a new list containing each value as an element. For example:

 

> (list ´1 ´2 ´3)
(1 2 3)
> (list ´a ´(b c) ´d)
(a (b c) d)

append

append takes two arguments, which should both evaluate to lists, and creates a new list by concatenating the given lists. For example:

 

> (append ´(a b) ´(c d))
(a b c d)

append can also produce dotted pairs:

 

(append ´(a b) ´c) -> (a b . c)

[back to top]


2.3 Predicates

A predicate is a symbolic expression which evaluates to true ( t ) or false ( nil ), i.e. it is a test.

Logical operators

The following logical operators are defined: not , and , or .

atom

atom determines whether or not its argument is an atom, for example:

 

> (atom ´a)
t
> (atom ´(a b c))
nil

listp

listp determines whether something is a list. For example:

 

> (listp ´a)
nil
> (listp ´(a b c))
t

[back to top]


2.4 Conditionals

Predicates can be used to make choices, but to do this the equivalent of a conditional branch is needed. For this the cond (for conditional) function is provided. cond is similar to the "if; then; and else" statements.

A cond s-expression can have any number of arguments (clauses), which consist of a series of expressions. The first element of a cond clause is treated as a condition to be tested for; the rest consists of things to do should the condition prevail.

 

> (cond
   (predicate1 action1a action1b action1c ...)
   (predicate2 action2a action2b action2c ...)
   .
   .
   (t default_action1 default_action2 ...)
)

meaning:

 

if
    predicate1 is true, then evaluate action1a,
    action1b, etc. in sequence
else if
    predicate2 is true, then evaluate action2a ...
    .
    .
else
    evaluate default_action1, ...

A cond clause is only fully evaluated providing that the first element of the clause evaluates to true t .

For example, if you want to be sure that something is a list before you take its car , do:

 

> (cond ((listp x) (car x)))

This previous example is a cond of one clause, the s-expression ((listp x) (car x)) . Where the first element of the clause is (listp x) which is the condition of the clause. It is only when this evaluates to true that LISP evaluates the rest of the clause, the expression (car x) . For example:

 

> (setq x ´(a b c))
(a b c)
> (cond ((listp x ) (car x)))
a
> (setq x ´y)
y
> (cond ((listp x) (car x)))
nil

Like other LISP functions, cond always returns a value. In the previous example, when the test in the cond clause evaluates to true, LISP evaluates the next expression, whilst returning the value of that expression as the value of cond . When the test failed, the cond returned nil .

[back to top]


2.5 User-defined functions

A LISP user can create functions using the function defun (define function).

defun

defun takes as its arguments the name of the function to be defined, a list of formal parameters (literal atoms), and some bodies of code (s-expressions). defun does not evaluate any of these arguments, it associates, for future reference, the formal parameter list and bodies of code with the given function name.

For example, to create the simple function addthree :

 

> (defun addthree (x) (plus x 3))
addthree
> (addthree 4)
7

More generally, the syntax of a call to defun would look like:

 

> (defun function_name (param1 param2 ... paramn)
    (... s-expression1 ...)
    (... s-expression2 ...
    (... s-expression2 ...)
    .
    .
)

[back to top]


2.6 Recursion vs. iteration

At times we want to repeat an operation an indefinite number of times, each time with different inputs. This can be achieved through the use of iteration or recursion.

[back to top]

2.6.1 Recursion

By using recursion we can accomplish the equivalent of indefinite repetition; a function is said to be recursive if it refers to itself in its definition. It is necessary to make sure that the function checks first for a termination condition, to avoid an infinite loop. For example:

 

> (defun fac (n)
    (cond
        ((eq n 0) 1)
        (t (times n (fac (sub1 n))))
    )
    )
fac
> (fac 4)
24

[back to top]

2.6.2 Iteration

In iterative code, indefinite repetition is designated by explicit instructions to do something repeatedly. In LISP there are several functions that enable you to write an explicit loop

mapc

mapc is a "LISP-like" way of doing an iteration, in which it takes two arguments; the first being a list and the second a function. For example:

 

> ( mapc list_name function_name )

mapc maps each element of list_name by applying function_name (which must be a single argument) to it, for example:

 

> ( mapc ´( 2 5 7 ) add1 )
( 3 6 8 )

[back to top]


2.7 Special features of Parasolid LISP

Parasolid LISP provides a more extensive set of LISP facilities than those which are generally found in other LISP dialects, important points worth noting are listed below:

 

( apply 'eval ( list plus 1 1 ) )

Quick reference summary

For a quick reference table summary of the functions available in PARASOLID LISP, see Appendix B, "Parasolid LISP Functions".

Error codes

The error codes in PARASOLID LISP are given in Appendix D, "List of Parasolid LISP Functions".

[back to top]


2.8 Object oriented LISP

Parasolid LISP has been extended by the inclusion of object-oriented functions and these are used extensively within KID.

Object-oriented expressions have the form:

 

(object function argument1 argument2 ...)

The functions listed first are extensions to functional LISP rather than object oriented themselves:

 

> ( define <object> <class> )

 

> ( undefine <objects> )

Object oriented LISP provides many more useful functions to add to those described for standard LISP. Below is a summary of such functions which are properties of the universe class. Try using (universe help _<name_>) for more information.

 

> ( fred help [property] ) --> useful information

 

> ( define limb fred ) --> limb
> ( define left_leg limb ) --> left_leg
> ( define right_leg limb ) --> right_leg
> ( fred is ) --> man
> ( left_leg is ) --> limb
> ( left_leg is man ) --> fred
> ( left_leg is fred ) --> limb

 

> ( left_leg supertree ) --> (left_leg limb fred man universe)

 

> ( fred age 33 ) --> 33
> ( fred age ) --> 33
> ( fred - age ) --> t
> ( fred age ) --> undefined

The following object functions are used internally in KID and need not concern the user. They are reserved words and should not be overwritten.

 

PROPERTY FUNCTIONP INHERIT SYSTEM SUBJECT LAZY GUARD LISTENER UNGUARD OWN OWNER RESUME ABANDON 

[back to top]

<<< Kernel Interface Driver (KID) - an Overview Chapters Object-Oriented KID >>>