| OPERATING CLISP |
Starting CLISP
$ clisp
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Welcome to GNU CLISP 2.42 (2007-10-16)
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2007
>
Open a File
> (load "/path/to/file.lp")
;; Loading file /path/to/file.lp ...
;; Loaded file /path/to/file.lp
T
Handling Errors
When handling errors, the user is given the ability to see an error report, and to see different options
they have to fix the error. Here, we can see that there is only one restart available, R1. If R1 is triggered
then the code will abort the operation. We also could have typed abort. Using abort to quit out of an error
will always return back out of all of the different break points.
> (expt 5)
*** - EVAL: too few arguments given to EXPT: (EXPT 5)
The following restarts are available:
ABORT :R1 ABORT
Break 1 > :R1
>
Were we still inside of a break point, we could have typed 'help' to see some of the other available debugging
options, including the ability to inspect an error, and the ability to back-trace what caused the error. Here is
the help information
Commands may be abbreviated as shown in the second column.
COMMAND ABBR DESCRIPTION
Help :h, ? this command list
Error :e Print the last error message
Inspect :i Inspect the last error
Abort :a abort to the next recent input loop
Unwind :uw abort to the next recent input loop
Reset :re toggle *PACKAGE* and *READTABLE* between the
local bindings and the sane values
Quit :q quit to the top-level input loop
Mode-1 :m1 inspect all the stack elements
Mode-2 :m2 inspect all the frames
Mode-3 :m3 inspect only lexical frames
Mode-4 :m4 inspect only EVAL and APPLY frames (default)
Mode-5 :m5 inspect only APPLY frames
Where :w inspect this frame
Up :u go up one frame, inspect it
Top :t go to top frame, inspect it
Down :d go down one frame, inspect it
Bottom :b go to bottom (most recent) frame, inspect it
Backtrace-1 :bt1 list all stack elements
Backtrace-2 :bt2 list all frames
Backtrace-3 :bt3 list all lexical frames
Backtrace-4 :bt4 list all EVAL and APPLY frames
Backtrace-5 :bt5 list all APPLY frames
Backtrace :bt list stack in current mode
Backtrace-l :bl list stack in current mode.
Limit of frames to print will be prompted for.
Frame-limit :fl set the frame-limit. This many frames will
be printed in a backtrace at most.
Break+ :br+ set breakpoint in EVAL frame
Break- :br- disable breakpoint in EVAL frame
Redo :rd re-evaluate form in EVAL frame
Return :rt leave EVAL frame, prescribing the return values
The following restarts are available:
ABORT :R1 ABORT
Getting help on a function
CLISP allows the user to retrieve help on any function they would like to use by calling
'description' with the name of the function they would like help on. Here is an example:
> (describe 'cos)
COS is the symbol COS, lies in #, is accessible in 15
packages ASDF, CLOS, COMMON-LISP, COMMON-LISP-CONTROLLER, COMMON-LISP-USER,
EXPORTING, EXT, FFI, POSIX, READLINE, REGEXP, SCREEN, SYSTEM, XLIB, XPM, names
a function.
#<PACKAGE COMMON-LISP> is the package named COMMON-LISP. It has 2 nicknames
LISP, CL.
It imports the external symbols of 1 package CLOS and exports 978 symbols to
14 packages ASDF, COMMON-LISP-CONTROLLER, XLIB, XPM, READLINE, REGEXP,
POSIX, EXPORTING, FFI, SCREEN, CLOS, COMMON-LISP-USER, EXT, SYSTEM.
#<SYSTEM-FUNCTION COS> is a built-in system function.
Argument list: (#:ARG0)
For more information, evaluate (DISASSEMBLE #'COS).
>
Quitting
> (quit)
Bye.
|
| COMMENTS |
|
OVERVIEW
Comments in Lisp, like most other languages, are for the purpose of documentation. Lisp also has an added comment type that allows one to get a description of a function without having to look at the code file. This style of comment is called a Function Description Comment.
Single Line Comments
;single line comments are started with a semi-colon
Block Comments
#|
this is a block comment, it will
allow the programmer to comment out multiple lines.
It is also good for commenting out broken functions, etc.
|#
Function Description Comments
(defun double (x)
"This multiplies the passed argument by two"
(* x 2))
|
| SYMBOLS |
|
OVERVIEW
A symbol in Lisp is simply any string of characters, numbers, and hyphens. Generally, user defined symbols should start with a character; however, this is not a strictly enforced style.
Set the value of a Symbol
> (setq a 10)
10
Pass a symbol as an argument to a function
> (+ a 10)
20
Temporarily set value of a symbol
> (let ((a 5)) (* a 10))
50
> a
10
Reserved Symbols
Lisp reserves the symbols t and nil. t stands for true, and nil stands for false. These symbols can not be changed.
|
| NUMBERS |
|
OVERVIEW
Numbers in Lisp are a string of digits that can optionally be preceded by a + or -. Lisp has built in facilities to handle real, rational, and complex numbers. Most standard arithmetic functions are available for use, including (but not limited to) +, -, /, *, floor, ceiling, mod, trigonometric functions, etc. Lisp does not limit the memory allocated to a single number, and will support large integers up to the largest size the available memory supports. Using large integers, or bignum's will significantly increase computation time.
Number Types
> 32
32
> -17
-17
> 3/4
3/4
> 3.141592653589
3.141592653589
> 1.06e-23
1.06e-23
> #c(3.14 0.75)
#C(3.14 0.75)
Arithmetic Operations
> (exp 1)
2.7182817
> (+ 4 1/4)
17/4
> (expt 3 4)
81
> (+ 1 2 3 (* 4 5 6))
126
|
| CONSES |
|
OVERVIEW
Conses are simple, two field records. They are the foundation for lists, trees, and many other structures that can be used very successfully in lisp code. Cons allow setting and retrieving each field separately, namely with the car and cdr functions.
Allocate a cons
> (cons 5 4)
(4 . 5)
car and cdr
> (car (cons 4 5)) ;first can be used as a synonym for car
4
> (cdr (cons 4 5)) ;rest is a synonym for cdr
5
> (setq a (cons 10 20))
(10 . 20)
> (car a)
10
> (setf (cdr a) 30) ;here, we see the set field function
30
> a
(10 . 30)
|
| LISTS |
|
OVERVIEW
As the name Lisp implies (List Processing), lisp handles lists very well. The simplest, and most frequently used, list is a linked list. Linked lists are made by using stacked conses. The car of each cons is an element in the list, and the cdr of each one is the link to the next element. The cdr can either be another cons (allowing for another element in the list), or it can be nil, signifying the end of the list. To help keep notation clean and compact, this style of list can be accomplished with the list function.
Making a list
> (list 4 5 6)
(4 5 6)
> (cons 4 (cons 5 (cons 6 nil)))
(4 5 6)
Appending lists together
> (append (list 4 5 6) (list 7 8 9))
(4 5 6 7 8 9)
Remove element from list by value
> (delete 4 (list 1 2 4 3 4 5 2))
(1 2 3 5 2)
Sorting a list
> (sort (list 1 2 4 3 4 5 2) #'>)
(1 2 2 3 4 4 5)
Using a list as a tree
> (setq a (list 1 2 3 4))
(1 2 3 4)
> (setq b (list 5 6 7 a))
(5 6 7 (1 2 3 4))
> (list 'a 'b 1 2 a) ;if you just want to include the character, put a single quote before it
(A B 1 2 (1 2 3 4))
There are many other list operations that can be preformed easily. These include sorting, reversing, mapping, pushing, popping, and much more. Do not write a function if someone else might have already written it, it is probably part of the available code.
Note: When printing the contents of a linked list to the screen, lisp will omit the dot seen in regular cons notation if the cdr is another cons, or if the cdr is nil (meaning the end of the linked list).
|
| MAPPING |
|
OVERVIEW
Mapping is one of the most outstanding features in lisp. Mapping allows the user to apply
a function over all of the items in a list, vector, or other structure. MAPCAR, MAPC, and MAPCAN
process successive list elements. MAPLIST, MAPL, and MAPCON will process lists and successive sublists.
MAP and MAP-INTO work on multiple sequence types, not just lists.
MAPCAR
MAPCAR simply applies the passed function against the rest of the arguments supplied.
> (mapcar #'+ (list 1 2 3) (list 4 5 6))
(5 7 9)
MAPC
MAPC is similar to MAPCAR, except that instead of generating a new list and returning it,
just returns the first list passed in
> (mapc #'(lambda (x y) (print (* x y))) (list 1 0 2) (list 3 4 5))
3
0
10
(1 0 2)
MAPLIST
MAPLIST works like MAPCAR, but generates a list of the results of the function executed
on the lists, and all of the successive sublists.
> (maplist #'list (list 1 2 3) (list 4 5 6))
(((1 2 3) (4 5 6)) ((2 3) (5 6)) ((3) (6)))
MAPL
MAPL is like MAPC in that it does not generate a new list and return it, but it also processes
all of the lists given as arguments, and their successive sublists. MAPL returns the first passed list.
> (mapl #'(lambda (x y) (print (append x y))) (list 1 0 2) (list 3 4 5))
(1 0 2 3 4 5)
(0 2 4 5)
(2 5)
(1 0 2)
MAP
MAP works on lists, vectors, and nil. It operates much like MAPCAR, but lets you define what type it is
operating over. When operating on nil, MAP always returns NIL.
> (map nil #'+ (list 1 2 3) (list 4 5 6))
NIL
> (map 'list #'+ (list 1 2 3) (list 4 5 6))
(5 7 9)
> (map 'vector #'+ (list 1 2 3) (list 4 5 6))
#(5 7 9)
> (map '(vector number 3) #'+ (list 1 2 3) (list 4 5 6))
#(5 7 9)
|
| FUNCTIONS |
|
OVERVIEW
Lisp, being a functional language, uses nested functions to accomplish tasks very effectively.
This also means that being able to write an effective function can mean the difference between clean code
and an atrocity infested with bugs. Most simple actions in lisp are functions - this includes +, -, list, append
etc.
Using a Function
> (+ 4 5 6)
15
> (append (list 1 2) (list 3 4))
(1 2 3 4)
Defining a Function
> (defun add-two (x) (+ 2 x))
ADD-TWO
> (add-two 5)
7
> (defun small-math (x) ;functions with multiple statements
(setq x (* x 3)) ;will return the value of the last statement
(setq x (+ x 2))
(+ x 1))
SMALL-MATH
> (small-math 5)
18
Functions with optional arguments
A function can be defined that takes an optional number of arguments. This is accomplished
by using the &optional symbol. Any arguments after &optional in the argument list are optional.
> (defun optional-func (x &optional y)
(if y x 0))
OPTIONAL-FUNC
> (optional-func 5)
0
> (optional-func 5 10)
5
> (defun another-func (x &optional (y 4)) ;we can also use this notation to give optional arguments
(+ x y)) ;default values
ANOTHER-FUNC
> (another-func 5)
9
> (another-func 5 10)
15
Functions with unlimited arguments
A function can be created that takes unlimited arguments by passing the
&rest argument followed by a parameter. The parameter then collects the rest
of the passed arguments in a list for processing, and binds it to the symbol.
> (defun return-rest (x &rest y) y)
RETURN-REST
> (return-rest 5)
NIL
> (return-rest 5 10 15 20)
(10 15 20)
Keyword Arguments
Keyword arguments allow the user to pass arguments in any order because they are associated with keywords.
> (defun key-func (&key x y) (cons x y))
KEY-FUNC
> (key-func :y 10)
(NIL . 10)
> (key-func :x 5 :y 10)
(5 . 10)
> (key-func)
(NIL)
Passing a function as an argument
There are two ways to pass a function as an argument, you can either use the 'function'
function, or the the prefix of #'.
> #'+
#<SYSTEM-FUNCTION +>
> (function +)
#<SYSTEM-FUNCTION +>
> (defun callfunc (x) (funcall x 2 3))
CALLFUNC
> (callfunc #'+)
5
> (callfunc (function *))
|
| PRINTING |
|
OVERVIEW
Like with most other languages, lisp has the ability to print various forms
of data to the console. This is mainly accomplished with the print and format functions.
The print function allows simple and easy printing of variables, and the format function
allows formatted output.
print Function
> (print 5)
5 ;this is the '5' that is printed
5 ;this is the '5' that is returned
format Function
The format function's second argument is either t, nil, or a stream. If the argument is
t, then the output goes to terminal. If the argument is nil, then the function prints nothing
and instead returns a string representation. If the argument is a stream, then the output is sent
over that stream.
> (format t "an atom: ~S, a list: ~S and ~% an integer: ~D" nil (list 10 5 15) 44)
an atom: NIL, a list: (10 5 15) and
an integer: 44
NIL
|
| ARRAYS |
|
OVERVIEW
Arrays are one of the simpler structures in lisp - they are very similar to arrays in other languages, but are
not limited by having a single type. The 'make-array' command makes an array, and the 'aref' command allows the user to reference an
element of an array.
Making an Array
> (make-array '(3 3)) ;here, we are passing a list, not what it executes to, so we use the '
#2A((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL))
> (make-array 4) ;no need for parens on single dimensional arrays
(NIL NIL NIL NIL)
Accessing an Array
> (aref (make-array 4) 1)
NIL
Note: Array indices always start at 0
|
| STRINGS |
|
OVERVIEW
Strings in Lisp are much like strings in C in that they are stored as a single dimensional character array. To use a string
in lisp, we can simply place a sequence of characters in double quotes. If you want to write a string that has a double quote,
the quotation mark can be preceded by a backslash (as an escaping character). Here is an example:
> "Look! A String with a \""
"Look! A String with a \""
Notably, a string executes to itself.
Get the length of a string
> (length "hi there")
8
Access a character in a string
> (char "abc" 1)
#\b ;this is lisp's notation for a character
> (aref "abc" 1)
#\b ;remember, strings are just arrays
Concatenate strings
> (concatenate 'string "abc" "def")
"abcdef"
|
| STRUCTURES |
|
OVERVIEW
Structures in lisp are very similar to structures in C, or records in Pascal. They allow data to be stored and accessed
with an associated keyword. To define a struct, you simply need to call the 'defstruct' method with the name
of the struct and the keywords of its members. Once a structure definition is made, then functions to make a new instance and access its fields are
also made available.
Defining a Structure
> (defstruct foo ;name of the struct is foo
alpha
bravo
charlie)
FOO
We now have the commands 'make-foo', 'foo-alpha', 'foo-bravo', and 'foo-charlie' available for use.
Make instance of structure
> (make-foo)
#s(FOO :ALPHA NIL :BRAVO NIL :CHARLIE NIL)
> (make-foo :bravo "a string!")
#s(FOO :ALPHA NIL :BRAVO "a string!" :CHARLIE NIL) ;we can also define a value for a field when creating the structure instance.
Access member in structure
> (foo-bravo (make-foo :bravo "a string!"))
"a string!"
Alter value of field in structure
> (setq a (make-foo))
#S(FOO :ALPHA NIL :BRAVO NIL :CHARLIE NIL)
> (setf (foo-charlie a) '(1 2 3))
(1 2 3)
> a
#S(FOO :ALPHA NIL :BRAVO NIL :CHARLIE (1 2 3))
'setf' allows us to set a field within a structure
|
| CONDITIONALS |
|
OVERVIEW
Like with most other languages, conditionals (often in the form of the classic 'if' and 'then', play a huge part in the operation
of lisp programs. Lisp uses the atom 'nil' to mean false, and anything else to mean true. If a program is being written that needs to have the
ability to generate a boolean value, the most often used atom to represent true is 't'. Lisp provides the logical operators and, or, not, and
the like for simple boolean manipulation. The most basic of the lisp conditional is the 'if' function, but lisp also provides an if-else like
function called cond and a couple others.
Using if statements
If statements are in the form (if boolean_value then_value else_value).
> (if NIL 5 6)
6
> (if 4 5 6)
5
Using when statements
'when' statements are much like if statements, except take an unlimited number of arguments, checking if the first one is not nil, then executing
the remainder.
> (when t
(print "Hello"))
"Hello" ;printed value
"Hello" ;returned value
> (when nil
(print "World!"))
NIL
Using cond
'cond' is equivalent to a set of if...else if..else if... statements.
> (setq a 87)
87
> (cond
((> a 90) "Great job!")
((> a 80) "OK job!")
((> a 70) "Do better!")
((> a 60) "Do something!")
(t "Go home!")) ;if nothing else has already been true, it will execute this
"OK job!"
Using the case statement
> (setq a 'Y)
B
> (case a
(w 5)
((x y) 6) ;x or y
((z i) 7) ;z or i
(otherwise 8))
6
|
| ITERATIONS |
|
OVERVIEW
The simplest iteration function in lisp is 'loop', a construct that simply iterates over its body until it hits the 'return' special form (special
forms are things in lisp that look like functions but are not. Unfortunately, they are out of the scope of this document.
Simple use of 'loop'
> (setq x 0)
0
> (loop
(setq x (+ x 1))
(print x)
(if (= x 10) (return NIL)))
1
2
3
4
5
6
7
8
9
10
NIL
Using 'dolist'
'dolist' binds a locally scoped variable to each element in a list successively and executes until it reaches the end of the list
> (dolist (x '(A B C))
(print x))
A
B
C
NIL
Note:dolist will always return nil
|
| SORTING |
|
OVERVIEW
Lisp provides a couple of easy to use sorting functions called 'sort' and 'sort' stable. The functions are allowed to be
destructive functions, however, so they may destroy the arguments that are passed into them. We can avoid this by calling
copy-list or copy-tree if needed. sort also takes a function for it to use for comparison., in the examples below, we use
the greater than and less than functions; however, any function could be used. sort-stable is the stable version of sort, meaning that
if there are two elements that are equal according to the comparison function, they will occur in the same order in the sorted list
as they do in the unsorted list
Using sort
> (sort '(4 2 5 5 6 2) #'>)
(6 5 5 4 2 2)
> (sort '(6 5 4 3 2 1) #'<)
(1 2 3 4 5 6)
|
| EQUALITY |
|
OVERVIEW
Lisp provides a number of functions for comparing to see if two thing are equal. It is important
to always use a function that actually compares the objects in the manner intended, as different comparison functions
do not compare in the same way.
Comparing Numbers
> (= 4 4)
T
> (= 4 5)
NIL
> (= 4 4.0)
T
> (= 4 #c(4.0 0))
T
Comparing memory addresses
> (setq x (cons 'a 'b))
(A . B)
> (setq y x)
(A . B)
> (eq x y)
T
> (eq (cons 'a 'b) (cons 'a 'b))
NIL
|
| FILE SYSTEM ACCESS |
|
OVERVIEW
Lisp provides a large number of functions for accessing the file system for I/O purposes. Most of the functions are self
explanatory.
Open a file
> (open "/path/to/file")
#<INPUT BUFFERED FILE-STREAM CHARACTER #P"/path/to/file" @1>
Read from a file
> (let ((in (open "/path/to/file.txt")))
(format t "~a~%" (read-line in))
(close in))
Some text was in this file
T
Write to a file
> (with-open-file (stream "/some/file/name.txt" :direction :output)
(format stream "Some text."))
T
|
|