http://t3x.org/klisp/22/kl22.txt.html

The KILO LISP 22 Manual


By Nils M Holm, 2019, 2020


0 Quick Summary

For the impatient LISP user:

KILO LISP is a purely symbolic, lexically scoped
LISP system with tail call elimination, macros,
and image files. The only data types are the atom
(symbol) and the pair/list. T is true and NIL is
false. The following special forms exist:

Core:    APPLY IF IFNOT LAMBDA PROGN QUOTE SETQ
Derived: AND COND DEFMACRO DEFUN LABELS LET LETN
         LOOP OR QUASIQUOTE

The following functions are predefined:

Built-in: ATOM BINDING CAR CDR CONS EQ EOFP
          ERROR GC GENSYM LOAD PRIN1 PRINT READ
          RPLACA RPLACD SUSPEND 

Derived:  APPEND ASSOC CAAR ... CDDDR EQUAL
          FILTER (REMOVE-IF-NOT) FLATTEN LIST
          MACROEXPAND-1 MAPCAR MAPLIST MEMBER
          NOT NCONC NRECONC NREVERSE NULL PRIN
          REVAPPEND REVERSE TERPRI

The following syntactic sugar exists:

  'x  is  (quote x)
  @x  is  (quasiquote x)
  `x  is  (quasiquote x)
  ,x  is  (unquote x)
 ,@x  is  (unquote-splice x)
#xyz  is  (x y z)
   %  is  the EOT


1 S-Expressions

A Symbol is any combination of these characters:

a b c d e f g h i j k l m
n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 0 -

Other characters can be included by slashifying
them (prefixing them with a /).

An Atom is either a symbol or NIL.

A Pair is an ordered pair of two S-expressions:

(car-part . cdr-part)

The spaces before and after the dot are optional,
i.e.

(a . b)  =  (a.b)

A pair may contain other pairs:

((a . b) . c)
(a . (b . c))
((a . b) . (c . d))

An S-Expression is either an atom or a pair.

A nested pair of the form

(a . (b . c))   may be written as   (a b . c)

and

(a . nil)       may be written as   (a)

The rules apply inductively, so

(a . (b . (c . nil)))  =  (a b c)


1.1 Lists

A list is an S-expression that is either NIL or a
pair whose cdr part is a list:

List  =  NIL  or  (S-expression . List)

These are Lists:

nil
(foo)
(foo bar baz)
(foo (a . b) (nested list))

A list whose innermost/rightmost cdr part is a
symbol is called a Dotted List. These are dotted
lists:

(a b . c)
((foo bar) . baz)

The pair is a two-element dotted list.

A Word is a list of single-character symbols.
Words may be condensed (abbreviated) as follows:

(a b c)  =  #abc

Slashification works in words, so #a/*b is the
list (a * b).

An Association List (or Alist) is a list of pairs
(associations), where the car part of each
association is called the Key and the cdr part
the Value of the association:

((<key1> . <value1>) ... (<keyN> . <valueN>))

See ASSOC for details.


1.2 Comments

A comment may be inserted anywhere (even inside
of a form, but not inside of an atom) by
including a semicolon (;). Comments extend to the
end of the current line.

Example:

(setq foo  ; this is a comment
  (quote bar))


1.3 Unreadable Forms

A form that contains characters other than those
listed in the previous sections are unreadable,
i.e. they cannot be read by the LISP parser.

Unreadable forms are sometimes output by the
system to represent data that have no unambiguous
textual representation.


2 Expressions

An Expression is an S-expression with a meaning.

x => y     denotes that x evaluates to y;
           y is the Value of x.

undefined  denotes an undefined value.

There are four kinds of expressions:

Variables
Lambda Abstraction
Function Application
Special Forms

Strictly speaking, lambda abstraction is
also a special form, but it will be discussed
separately.


2.1 Variables

A Variable is a symbol that is bound to a Box.
A box is a container that contains a value.

Variables evaluate to the value that is stored
in their box:

Variable  =>  Value

References to unbound symbols (symbols that are
not bound to any box) are undefined:

unbound-symbol  =>  undefined

The term "the variable V is bound to the value X"
is short for "the variable V is bound to a box
containing the value X".

A Constant is a variable that is bound to its own
name:

constant  =>  constant

For instance, the canonical "true" value, T, is a
constant:

t  =>  t

Variables are created by the SETQ special form or
by lambda abstraction.


2.2 Lambda Abstraction

(Lambda <vars> <body>)

is a Lambda Abstraction. Its value is a Function.

Names enclosed in angle brackets are
Meta-Syntactic Variables. They are not part of
LISP, but describe parts of special forms. They
may represent single expressions or sequences of
expressions.

<Vars> is a list of variables of a function and
<body> is the Term or Body of a function.

<Vars> may be

- a variable
- a list of variables
- a dotted list of variables

<Body> must be at least one expression.

Examples: (lambda (x) x)
          (lambda (f x) (print 'f) (f x))
          (lambda () (print (quote hello/ world)))
          (lambda x x)

The variables of a function are created by the
function by binding their names to boxes
containing the arguments of the function. This
happens when the function is being applied to
some arguments.


2.3 Function Application

A variable X is Bound in an expression E, if

- E is a lambda function
AND
- X is a variable of E

Examples:

X  is     bound in  (lambda (x) (f x))
F  is not bound in  (lambda (x) (f x))

When a variable X is not bound in an expression E,
X is Free in E; X is a free variable of E.

A function is Applied to Arguments using the
syntax

(function argument ...)

The following steps are involved in the
application:

(1) each expression in the application is
    evaluated
(2) a box is created for each variable of the
    function
(3) each argument is stored in the corresponding
    box
(4) the body of the function is evaluated
(5) the value of the body is returned

Because of (1), functions may be bound to
variables. In step (1), a variable bound to a
function will be replaced by that function.

Variables are associated with arguments by
position, i.e. the first argument is stored in
the first variable, etc.

For instance:

((lambda (x y) (cons x y)) (quote 1) (quote 2))

; evaluate arguments:
; (quote 1) => 1,  (quote 2) => 2
((lambda (x y) (cons x y)) 1 2)

; create variables and store 1 in X and 2 in Y,
; giving the body
(cons 1 2)

; evaluate the body, giving the value
(1 . 2)


2.4 Optional Arguments

When the list of function variables is a proper
(NIL-terminated) list, there has to be exactly
one argument per variable:

((lambda (x) x))         =>  undefined
((lambda (x) x) 'a)      =>  A
((lambda (x) x) 'a 'b))  =>  undefined

When the argument list of a function is a dotted
list, the variables before the dot bind like
fixed arguments, above, and the variable after
the dot binds to a list containing any excess
arguments that may be passed to the function:

((lambda (x . y) y))            =>  undefined
((lambda (x . y) y) 'a)         =>  nil
((lambda (x . y) y) 'a 'b))     =>  (b)
((lambda (x . y) y) 'a 'b 'c))  =>  (b c)
...

When there are no fixed arguments, the list of
function variables is replaced with a single
variable that binds to a list of all arguments:

((lambda x x))         =>  nil
((lambda x x) 'a)      =>  (a)
((lambda x x) 'a 'b))  =>  (a b)
...


3 Special Forms

A Special Form is an expression of the form

(<keyword> <argument> ...)

The syntax is the same as in function application,
but there are some differences: When a syntactic
Keyword is found in the first slot of a list,
neither the keyword nor any <argument>s will be
evaluated. The <argument>s will then be processed
by the LISP system according to the semantics of
the individual special form. The semantics may
involve the evaluation of some of the <argument>s.

A Keyword is sometimes also called a Special
Operator. The special operators of the KILO LISP
language are

APPLY  IF  IFNOT  LAMBDA  PROGN  QUOTE  SETQ


3.1 (LAMBDA <vars> EXPR1 EXPR2 ...)  =>  FUN

Create a new function with the variables <vars>
and the body (PROGN EXPR1 EXPR2 ...). The PROGN
special form is implied, i.e.

(lambda (x) a b c)

will be interpreted as

(lambda (x) (progn a b c))

<Vars> may be a list, a dotted list, or a single
variable.  See Function Application, above.

Examples:

(lambda (x) x)             ; identity function
(lambda (x) (car (cdr x))) ; CADR function
(lambda x x)               ; LIST function


3.2 (APPLY FUN LIST)  =>  EXPR

Apply FUN to the given LIST of arguments and
return the value delivered by the function.
Basically, APPLY does

X = (cons fun list)

and then evaluates X, but *without* evaluating
the arguments in LIST again.

FUN may be a built-in function or a lambda
function, but not a special operator (like
APPLY itself).

Example: (apply cons '(1 2))  =>  (1 . 2)


3.3 (QUOTE EXPR)  =>  EXPR

Return EXPR unevaluated.

The form  'x  is an abbreviation for (quote x).

Examples: (quote foo)      =>  foo
          (quote (car x))  =>  (car x)
          '(foo bar)       =>  (foo bar)


3.4 (IF EXPR1 EXPR2 EXPR3)  =>  EXPR

Evaluate EXPR1. When its value is not NIL,
evaluate EXPR2 and otherwise evaluate EXPR3.
Return the value of the expression evaluated
last.

EXPR1 is called the Predicate of the form.

Examples: (if t 'yes 'no)       =>  yes
          (if nil 'yes 'no)     =>  no
          (if (atom 'x) 'a 'b)  =>  a


3.5 (IFNOT EXPR1 EXPR2)  =>  EXPR

Evaluate EXPR1. When its value is not NIL, return
the value of EXPR1. Otherwise evaluate and return
EXPR2. In either case EXPR1 is only evaluated
once.

Examples: (ifnot 'foo 'bar)  =>  foo
          (ifnot nil 'bar)   =>  bar


3.6 (SETQ <var> EXPR)  =>  <var>

Evaluate EXPR and store its value in the box
bound to the variable <var>. Return <var>. When
<var> is not bound to any box, a fresh box will
be created and <var> will be bound to it.

Example: (setq foo 'bar)  =>  foo
         foo              =>  bar


3.7 (PROGN EXPR ...)  =>  EXPR

Evaluate all given expressions from the left to
the right and return the value of the rightmost
expression. The special form (progn) evaluates to
NIL.

Examples:

(progn '1 '2 '3)      =>  3

(progn (print 'foo)   ; print foo, then print bar
       (print 'bar))  =>  bar


4 Derived Special Forms

A Derived Special Form is a special form that is
being transformed by the LISP system to an
expression that uses only function application
and the (primitive) special forms listed in the
previous chapter.

A function transforming a derived special form to
a primitive expression is called a Macro.

A macro is defined using the SETQ, MACRO, and
LAMBDA special forms:

(setq <var>
  (macro
    (lambda ...)))

The transformation of a derived special form is
called Macro Expansion. It is part of the
evaluation process and happens after reading but
before interpreting an expression.

The transformation is performed by passing the
arguments of the derived special form to the
(function contained in the) macro and then
replacing the derived special form by the result
of the macro.

The result of macro expansion can contain
more derived special forms, which will also
be expanded.

Examples:

(setq kwote
  (macro
    (lambda (x)
      (list 'quote x))))

This macro will expand the derived special form
(kwote foo) to the expression (quote foo), no
matter what FOO is. The result of the form is FOO.

(setq listq
  (macro
    (lambda x
      (if (null x)
          nil
          (list 'cons
                (list 'quote (car x))
                (cons 'listq (cdr x)))))))

This macro will expand the derived special form

(listq a b c)

to           (cons (quote a)
                   (listq b c))

then to      (cons (quote a)
                   (cons (quote b)
                         (listq c)))

then to      (cons (quote a)
                   (cons (quote b)
                         (cons (quote c)
                               (listq))))

and then to  (cons (quote a)
                   (cons (quote b)
                         (cons (quote c) nil)))

which no longer contains any derived special
forms. The last expression in the process is then
interpreted, giving the result (a b c).

The LISTQ macro can be implemented more
comprehensibly using quasiquotation -- see
QUASIQUOTE at the end of this chapter.


4.1 (GENSYM)  =>  SYMBOL

Generate a unique symbol name.

Rationale: When derived special forms expand to
expressions containing local variables, these
variables should be named using GENSYM. Otherwise
name capturing can occur, as the following
example illustrates:

(setq swap
  (macro
    (lambda (x y)
      @(let ((L ,x))
         (setq ,x ,y)
         (setq ,y L)))))

It is supposed to swap the values of X and Y,
but the local name L is captured when expanding
(swap L M), which does nothing:

(let ((L L)) (setq L M) (setq M L))

(It creates a local L and initializes it with the
 outer L, then sets the local L to M and then M
 to the local L.)

The proper way to implement the SWAP macro would
be:

(setq swap
  (macro
    (lambda (x y)
      (let ((g (gensym)))
        @(let ((,g ,x))
           (setq ,x ,y)
           (setq ,y ,g))))))

Example: (list (gensym)
               (gensym)
               (gensym))  =>  (G1 G2 G3)


4.2 (DEFUN <name> <vars> <body>)  =>  <name>

Define function <name> with the given variables
and body (see LAMBDA). The DEFUN form is an
abbreviation of

(setq <name> (lambda <vars> <body>))

Example: (defun fourth (x) (car (cdddr x)))


4.2 (DEFMACRO <name> <vars> <body>)  =>  <name>

Define macro <name> with the given variables
body (see MACRO). The DEFMACRO form is an
abbreviation of

(setq <name> (macro (lambda <vars> <body>)))

Example: (defmacro kwote (x) @(quote ,x))


4.4 (LET <bindings> <body>)  =>  EXPR

<Bindings> has the form
((<var1> EXPR1) ... (<varN> EXPRn))
and <body> is an implied PROGN form.

Create the variables <var1> through <varN>, then
evaluate the expressions in no specific order and
store their values in the corresponding variables.
Finally evaluate <body> and return its value.

Examples: (let ((a '1) (b '2))
            (cons a b))             =>  (1 . 2)

          (let ((a 'foo)) '1 '2 a)  =>  foo

          (let ((a '1))
            (let ((a (cons a '2)))
              a))                   =>  (1 . 2)


4.5 (LETN <bindings> <body>)  =>  EXPR

<Bindings> has the form
((<var1> EXPR1) ... (<varN> EXPRn))
and <body> is an implied PROGN form.

Create the variable <var1>, evaluate EXPR1 and
store its value in <var1>. With that binding in
place create <var2>, evaluate EXPR2, and store
its value in <var2>, etc.

I.e., each EXPRi evaluates in a context where all
<varJ> for J<i are already bound to their
corresponding values.

LETN is short for "LET nested". In other dialects
of LISP it is called LET*.

Examples: (letn ((a '1) (b a)) a)  =>  1

          (letn ((x nil)
                 (x (cons '3 x))
                 (x (cons '2 x))
                 (x (cons '1 x)))
            x)                     => (1 2 3)


4.6 (LABELS <bindings> <body>)  =>  EXPR

<Bindings> has the form
((<name1> <vars1> <body1>) ...)
and each <body> is an implied PROGN form.

Create the variables <name1> through <nameN>
and bind them to the corresponding functions
(lambda <vars1> <body1>), etc. Then evaluate
<body> and return its value.

Each <body> may refer to each <name>, thereby
allowing to create mutually recursive functions.

Examples:

(labels ((e (x) (if (null x) t   (o (cdr x))))
         (o (x) (if (null x) nil (e (cdr x)))))
  (e '#1234))                               =>  t


4.7 (AND EXPR ...)  =>  EXPR

Evaluate the given expressions, from left to
right, until one expression evaluates to NIL. In
this case return NIL. When none of the EXPRs
evaluates to NIL, return the value of the last
expression. When no arguments are given, return T.

This special form implements the short-circuit
logical AND.

Examples: (and)           =>  t
          (and '1 '2 '3)  =>  3
          (and nil 'foo)  =>  nil


4.8 (OR EXPR ...)  =>  EXPR

Evaluate the given expressions, from left to
right, until one expression evaluates to a value
other than NIL. In this case return the value.
When none of the EXPRs evaluates to non-NIL,
return NIL. When no arguments are given, return
NIL.

This special form implements the short-circuit
logical OR.

Examples: (or)           =>  nil
          (or '1 '2 '3)  =>  1
          (or nil 'foo)  =>  foo
          (or nil nil)   =>  nil


4.9 (COND <clause> ...)  =>  EXPR

Each <clause> has any of these forms:

(EXPR1 EXPR2 ...)
(EXPR1)
(T EXPR2 ...)

COND proceeds as follows:

The predicate EXPR1 of the first clause is
evaluated. When its value is not NIL, there are
two cases to distinguish:

(1) When the clause contains multiple
    expressions, the expressions EXPR2 ... will
    be evaluated from the left to the right and
    the value of the last expression will be
    returned. No other clauses will be examined.

(2) When the clause contains only the predicate
    EXPR1, the value of the predicate will be
    returned. No other clauses will be examined.
    EXPR1 will evaluate only once.

When the predicate of the first clause is NIL,
the predicate of the next clause will be
evaluated. Evaluation of COND ends when either
a clause with a true predicate is found or no
clauses are left to evaluate.

When there are no clauses left to evaluate, NIL
is returned.

When a clause has a predicate of the form T,
then the clause is assumed to be the last clause
in the COND form. All subsequent clauses will be
ignored.

Examples:

(cond (t 'first) (t 'second))    =>  first
(cond (nil 'a) (nil 'b) (t 'c))  =>  c
(cond (nil 'a) (t 'b))           =>  b
(cond (nil 'foo))                =>  nil
(cond)                           =>  nil


4.10 (LOOP <name> <bindings> <body>)  =>  EXPR

<Bindings> has the form
((<var1> EXPR1) ... (<varN> EXPRn))
and <body> is an implied PROGN form.

<Name> is a variable that will be bound to the
function

(lambda (<var1> ... <varN>) <body>)

and this function will then be applied to the
arguments EXPR1 through EXPRn. Hence applying
<name> to new arguments inside of <body> will
re-enter the loop with new values bound to the
given variables.

Examples:

; print (3 2 1), (2 1), (1)
(loop next ((a '(3 2 1)))
  (cond ((null a))
        (t (print a)
           (next (cdr a)))))  =>  t

; infinite loop
(loop next () (next))


4.11 (QUASIQUOTE <template>)  =>  EXPR

Create an S-expression from a Quasiquotation
template.

Quasiquotation is like quotation, but allows
to "unquote" parts of the quoted S-expression,
thereby inserting dynamic elements into an
otherwise static template.

The following abbreviations can be used:

@expr   =   (quasiquote expr)
`expr   =   (quasiquote expr)
,expr   =   (unquote expr)
,@expr  =   (unquote-splice expr)

The form (quasiquote template) quasiquotes an
S-expression.

The form (unquote expr) unquotes an S-expression
contained in a template.

The form (unquote-splice expr) is like UNQUOTE,
but splices the expression.

Formally,

          @a  =  (quote a)
         @,a  =  a
  @(a b ...)  =  (cons @a @(b ...)
 @(,a b ...)  =  (cons a @(b ...))
@(,@a b ...)  =  (append a @(b ...))

More intuitively, QUASIQUOTE creates an (often
nested) list structure and UNQUOTE replaces an
element in that structure with the value of its
argument. UNQUOTE-SPLICE replaces an element
with multiple elements that are passed to it as
a list. For instance:

@(a ,(list 'b 'c) d)  =>  (a (b c) d)

but

@(a ,@(list 'b 'c) d)  =>  (a b c d)

At the *end* of a list, a dot followed by
UNQUOTE can be used in the place of
UNQUOTE-SPLICE, thereby saving one application
of APPEND:

(x ,@y)  =  (x . ,y)

Quasiquotation is mostly used to create
expressions in macros. For instance, the KWOTE
macro from the beginning of section 4 can be
written as follows using QUASIQUOTE:

(defmacro kwote (x)
  @(quote ,x))

and the LISTQ example from the same section can
be written as

(defmacro listq x
  (if (null x)
      nil
      @(cons (quote ,(car x))
             (listq . ,(cdr x)))))


5 List Functions

5.1 (CONS EXPR1 EXPR1)  =>  EXPR

Create a fresh pair with EXPR1 as its car part
and EXPR2 as its cdr part.

Examples: (cons '1 '2)      =>  (1 . 2)
          (cons '1 '(2 3))  =>  (1 2 3)
                             ;  (1 . (2 3))
          (cons '(1 2) '3)  =>  ((1 2) . 3)


5.2 (CAR PAIR/NIL)  =>  EXPR
    (CDR PAIR/NIL)  =>  EXPR

CAR extracts the CAR part and CDR the cdr part of
a pair. (Car nil) and (cdr nil) are NIL.

Examples: (car '(1 . 2))  =>  1
          (car '(1))      =>  1
          (car '(1 2 3))  =>  1
          (cdr '(1 . 2))  =>  2
          (cdr '(1))      =>  nil
          (cdr '(1 2 3))  =>  (2 3)
          (car nil)       =>  nil


5.3 (CAAR PAIR)   =>  EXPR
    (CDDDR PAIR)  =>  EXPR

These functions extract elements from nested
pairs. These elements are extracted by the C..R
functions:

((caar . cdar) . (cadr . cddr))

And these elements by C...R:

 (  ((caaar . cdaar) . (cadar . cddar))
  . ((caadr . cdadr) . (caddr . cdddr))  )

E.g., CAAR extracts the car field of a car field,
CADR the car field of a cdr field, etc. The most
commonly used variants are these:

CADR   the second element of a list
CDDR   the tail of a list after the second elt.
CADDR  the third element of a list
CDDDR  the tail of a list after the third element

Examples: (cadr '(1 2 3 4))  =>  2
          (cddr '(1 2 3 4))  =>  (3 4)
          (cadr nil)         =>  nil

          (cadar '((lambda (x) t) 'foo))  =>  (x)


5.4 (RPLACA PAIR EXPR)  =>  PAIR
    (RPLACD PAIR EXPR)  =>  PAIR

RPLACA replaces the car part and RPLACD replaces
the cdr part of the given pair with EXPR. The
pair will be *modified*. Both functions return
the modified pair

Examples: (rplaca '(foo . bar) '0)  =>  (0 . bar)
          (rplacd '(foo . bar) '1)  =>  (foo . 1)

          (let ((x '(1)))      ; infinite
            (rplacd x x))  =>  (1 1 1 1 1 1 ...)


5.5 (LIST EXPR ...)  =>  LIST

Create a fresh list containing the values of the
given expressions.

Examples: (list)              =>  nil
          (list '1 '2 '3)     =>  (1 2 3)

          (list (cons '1 '2)
                (atom nil)
                (null 'x))    =>  ((1 . 2) t nil)


5.6 (REVAPPEND LIST EXPR)  =>  EXPR
    (NRECONC LIST EXPR)    =>  EXPR

Create a fresh list containing the elements of
LIST in reverse order and concatenate that list
to EXPR.

NRECONC is similar to REVAPPEND, but reverses and
concatenates its arguments destructively, so the
original argument values will be lost.

Examples:

(revappend '(1 2 3) '(a b c))  =>  (3 2 1 a b c)
(revappend '(1 2 3) '(a . b))  =>  (3 2 1 a . b)
(revappend '(1 2 3) 'a))       =>  (3 2 1 . a)
(revappend '(1 2 3) nil)       =>  (3 2 1)
(revappend nil 'a)             =>  a
(revappend nil '(a b c))       =>  (a b c)
(revappend nil nil)            =>  nil


5.7 (APPEND LIST ...)  =>  LIST
    (NCONC LIST ...)   =>  LIST

Create a fresh list containing the elements of
all LIST arguments in the given order. All LISTs
must be NIL-terminated.

NCONC is similar to APPEND, but concatenates its
arguments destructively, so the original argument
values will be lost.

Examples:

(append)                      =>  nil
(append '(a b) '(c d))        =>  (a b c d)
(append '(a) '(b) '(c) '(d))  =>  (a b c d)
(append '(a) nil nil '(b))    =>  (a b)


5.8 (REVERSE LIST)   =>  LIST
    (NREVERSE LIST)  =>  LIST

Create a fresh list containing the elements
of LIST in reverse order. LIST must be a
NIL-terminated list.

NREVERSE is similar to REVERSE, but reverses its
argument destructively, so the original argument
value will be lost.

Examples: (reverse '(1 2 3))  =>  (3 2 1)
          (reverse nil)       =>  nil


5.9 (MEMBER EXPR LIST)  =>  EXPR

Find the given EXPR in the given LIST. Return
the tail of LIST that starts with the first
occurrence of EXPR. When the expression is not
contained in the list, return NIL.

Examples: (member 'c '(a b c d e))  =>  (c d e)
          (member 'x '(a b c d e))  =>  nil
          (member '(b) '((a) (b)))  =>  ((b))


5.10 (ASSOC EXPR ALIST)  =>  EXPR

Find an association with the key EXPR in ALIST
and return it. When no association in ALIST has
EXPR as its key, return NIL.

Examples:

(assoc 'b '((a.1) (b.2) (c.3))  =>  (b . 2)
(assoc 'x '((a.1) (b.2) (c.3))  =>  nil
(assoc '(y) '((x).1) ((y).2))   =>  ((y) . 2)


5.11 (FLATTEN EXPR)  =>  LIST

Return a flat list containg all symbolic elements
of EXPR in the order in which they appear in EXPR.
When EXPR is a symbol, return a singleton list
containing that atom. If EXPR is NIL, return NIL.

Examples:

(flatten '(a . b))          =>  (a b)
(flatten '(a (b (c) d) e))  =>  (a b c d e)
(flatten 'foo)              =>  (foo)
(flatten nil)               =>  nil


6 Higher-Order Functions

6.1 (FILTER FUN LIST)         =>  LIST
    (REMOVE-IF-NOT FUN LIST)  =>  LIST

Return a fresh list containing all elements of
LIST that satisfy the predicate FUN.
REMOVE-IF-NOT is an unwieldy (but Common LISP-
compatible) alias of FILTER.

Examples:

(filter atom '(1 (2) 3 (4) 5))  =>  (1 3 5)

(filter (lambda (x) (not (null x)))
        '(foo () bar () () baz ()))
                                =>  (foo bar baz)


6.2 (MAPCAR FUN LIST1)        =>  LIST
    (MAPCAR FUN LIST1 LIST2)  =>  LIST

When one list is supplied, apply FUN to each of
its elements, returning a fresh list containing
the values of the function applications. I.e.:

        (mapcar f (list a1 ... aN))
equals  (list (f a1) ... (f aN))

When two lists are given, FUN is applied to
elements of the lists pairwise:

        (mapcar f (list a1 ... aN)
                  (list b1 ... bN)
equals  (list (f a1 b1) ... (f aN bN))

Examples:

(mapcar atom '(a (b) nil))  =>  (t nil t)

(mapcar cons '(a b c)
             '(1 2 3))  =>  ((a.1) (b.2) (c.3))


6.3 (MAPLIST FUN LIST1)        =>  LIST
    (MAPLIST FUN LIST1 LIST2)  =>  LIST

MAPLIST is like MAPCAR, but applies FUN to tails
of the given lists instead of individual elements.
I.e.:

        (maplist f (list a1 ... aN))
equals  (list (f (list a1 ... aN))
              ...
              (f (list aN)))

Example:

(maplist (lambda (x) x) '(b c d e))
                 => ((b c d e) (c d e) (d e) (e))


7 Predicates

A Predicate is a function that returns T or NIL.


7.1 (ATOM EXPR)  =>  T or NIL

Return T, if EXPR is an atom.

Examples: (atom 'foo)  =>  t
          (atom nil)   =>  t
          (atom '(x))  =>  nil


7.2 (NULL EXPR)  =>  T or NIL
    (NOT EXPR)   =>  T or NIL

Return T, if EXPR is NIL. Both predicates are the
same function, the difference between them is
intensional: NULL tests whether is argument is
the empty list and NOT negates the truth value of
its argument.

Examples: (null (cdr '(x)))  =>  t
          (not (atom 'x))    =>  nil


7.3 (EQ EXPR1 EXPR2)  =>  T or NIL

Return T, if EXPR1 and EXPR2 are the same object.
This is the case, if EXPR1 and EXPR2 are both

- the same symbol
- NIL
- bound to the same variable

In particular,

(eq (cons x nil)
    (cons x nil))        =>  nil

and

(let ((y (cons x nil)))
  (eq y y))              =>  t

for any S-expression X.

Examples: (eq 'foo 'foo)  =>  t
          (eq 'foo 'bar)  =>  nil
          (eq 'foo nil)   =>  nil
          (eq t t)        =>  t


7.4 (EQUAL EXPR1 EXPR2)  =>  T or NIL

Return T, if EXPR1 and EXPR2 are structurally
equal. This is the case, if 

- (eq EXPR1 EXPR2) => t
- (equal (car EXPR1) (car EXPR2)) => t
  and
  (equal (cdr EXPR1) (cdr EXPR2)) => t

(Eq a b) implies (equal a b), but the converse is
not true.

Informally, two S-expressions are equal, if PRIN1
emits the same output for them (but this is only
true, if both S-expressions have an unambiguous
textual representation).

Examples: (equal '(a (b) c) '(a (b) c))  =>  t
          (equal '(a (b) c) '(a (X) c))  =>  nil


7.5 (EOFP EXPR)  =>  T or NIL

Return T, if EXPR signals the end of input, as
returned by the READ function.

Example: (eofp (read)) %  =>  t


8 Program Loading

8.1 (LOAD SYMBOL)  =>  T

Read and evaluate expressions from the file
SYMBOL. The input from the file will be processed
as if typed in at the LISP prompt, but without
printing any values.

Nesting LOAD more than two times will cause an
error, i.e. it is possible to load a file F1 that
loads a file F2, but F2 cannot load any other
files.

Example: (load 'program)  =>  t


8.2 (SUSPEND SYMBOL)  =>  T

Write a LISP image to the file SYMBOL. The file
will contain the state of the LISP system at REPL
level, so it can be reinstated later by loading
the image. (It is not like the MACLISP SUSPEND
function, which captures the *entire* state of
the system so that it will restart where SUSPEND
returned).

An image is loaded by passing its name to the
LISP system when starting it (usually as a
command line argument).

The default image file name is "klisp".

Example:  (suspend 'klisp)  =>  t


9 Input and Output

These functions translate between the Internal
and Textual Representations of S-expressions.

The textual representation of an S-expressions
is what a user types in at the LISP prompt in
order to create a LISP object, like a symbol or a
list. The internal representation of that object
is what the LISP system uses internally to store
the object -- typically a set of pointers or
indexes and small integers.


9.1 (READ)  =>  EXPR

Read the textual representation of one object
from the current input source, convert it to
internal representation and return it.

Note that the value returned by READ on the REPL
will then be printed by PRINT (see below), which
converts it back to textual representation.
Hence the internal representation of an object
will never be visible to the programmer.

READ will skip over leading white space
characters and comments while reading input. It
will only return when a complete S-expression has
been read. When reading lists or pairs, the input
may span multiple lines.

When no input is available on the current input
source, READ will return a special object called
the End of Transmission Marker (or EOT marker).
The EOT marker will print as *eot* on the LISP
prompt.

An EOT marker can normally generated by pressing
"Control" and "d" (control-D) on the keyboard,
even on non-Unix systems, but not in "Pass"
mode (see REPL). KILO LISP will also interpret
the "%" character as an EOT marker.

Examples: (read) foo  =>  foo

          (read) (a
                  b
                  c)  =>  (a b c)

          (read) %    =>  *eot*


9.2 (PRIN EXPR)   =>  EXPR
    (PRIN1 EXPR)  =>  EXPR
    (PRINT EXPR)  =>  EXPR

All of these functions print the textual
representation of the given S-expression on the
current output device. They return the object
being printed.

PRIN1 just prints EXPR.
PRIN  prints a trailing blank after EXPR.
PRINT advances to the next line after printing
      EXPR.

Example: (prin 'foo)  =>  foo  ; prints "foo "


9.3 (TERPRI)  =>  SYMBOL

Print and return a newline character.

Example: (terpri)


10 Introspection Functions

10.1 (BINDING SYMBOL)  =>  EXPR

Return the current binding of the variable whose
name is the given symbol, or NIL if the symbol is
unbound.  The binding of a variable is a "box",
i.e. a singleton list containing the value of the
variable. Modifying the box will change the value
of the variable.

Examples:

(binding 'undefined)     =>  nil

(progn (setq foo 'bar)
       (binding 'foo))   =>  (bar)


10.2 (MACROEXPAND-1 EXPR)  =>  EXP

If (car EXPR) is a macro, expand the macro and
return the expanded form. Otherwise return EXPR
unchanged. Macro expansion of MACROEXPAND-1 is
non-recursive.

Examples:

(macroexpand-1 'foo)         =>  foo

(macroexpand-1 '(let ((x 'foo)) x))
                             =>  ((lambda (x) x)
                                  (quote foo))

(macroexpand-1 '(letn ((a '1) (b '2)) t))
                             => (let ((a '1))
                                  (letn ((b '2))
                                    t))


11 Misc. Functions

11.1 (ERROR SYMBOL)       =>  UNDEFINED
     (ERROR SYMBOL EXPR)  =>  UNDEFINED

Signal an error by printing a message and
aborting the computation in progress. The message
will consist of a question mark and the given
SYMBOL. When a second argument is given, it will
print after the SYMBOL, separated from it by a
colon. E.g.

(error 'don/'t/ do/ this/!)
                    will print   ? don't do this!

(error 'wrong 'foo)
                    will print   ? wrong: foo

The ERROR function delivers no value, because it
never returns.

Example: (if (atom x)
             (error 'need/ a/ list x)
             (do-something x))


11.2 (GC)       =>  NIL
     (GC EXPR)  =>  NIL

Perform a garbage collection. Note that garbage
collections are triggered automatically. This
function merely informs the programmer about
memory usage.

When NIL is passed to GC, all subsequent
automatic collections will be silent, and when
a non-NIL value is passed to GC, subsequent
collections will be verbose.

Example: (gc)  =>  number of free nodes


12 The REPL

The Read Eval Print Loop (REPL) is the interface
to the LISP system. It prints a prompt (*), reads
an expressions via READ, evaluates it, prints its
value using PRINT, and starts over.


12.1 Pass Mode

When the KILO LISP interpreter is started in
"pass" mode, input is read from SYSIN (stdin)
and output is written to SYSOUT (stdout). Pass
mode is activated by passing the command line
argument "-" to the interpreter.

In pass mode, input and output of the LISP system
can be redirected to files. Command line editing
will not work, and pressing Control-C will exit
the interpreter immediately. The interpreter will
also exit when the end of its input is reached.
(or when an end-of-text indiactor is entered at
the keyboard).

Pass mode is intended for batch processing.


12.2 Interactive Mode

While the REPL is reading input in interactive
mode, the following keys will have special
functions:

Control-B  move cursor left
Control-F  move cursor right
Control-A  move cursor to beginning of line
Control-E  move cursor to end of line
Control-H  delete char. on left (also backspace)
Control-P  rotate through last three input lines
Control-U  clear current input line
Control-C  abort all input, start over
Control-L  clear screen
Control-D  (on empty line) return EOT

Once a computation is in progress, it can be
aborted by pressing Control-C.

The value returned by a computation will be
bound to the variable IT, so it can be used
in the expression typed next:

* (cons '1 '(2 3))
(1 2 3)
* (cons '0 it)
(0 1 2 3)

To end the LISP session, press Control-D or enter
a % sign, both on an empty input line with no
lists open.


contact  |  privacy