Quick Lisp

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
References
Quick Lisp - Copyright (C) Adam Risi 2008