1. Overview of Lisp
This chapter can be used as a reference source.
1.1. Guide to lisp style
- Be specific.
- Use abstractions.
- Be concise.
- Use the provided tools.
- Don’t be obscure.
- Be consistent.
1.2. Special forms
1.2.1. Special forms for definitions
- defun
- defmacro
- defvar
- defparameter
- defconstant
- defstruct
1.2.2. Special forms for conditionals
It is poor style to use and
and or
for anything other than testing a logical condition. Use when, unless, if
if possible.
- when
- unless
- and
- or
- case
1.2.3. Special forms for dealing with variables and places
setf
(setf (rest list) nil)
- let
let*
(let* ((x 6) (y (* x x))) (+ x y))
- treat list as stack: pop, push
- (incf x) = (incf x 1) = (setf x (+ x 1))
- (decf x) = (decf x 1) = (setf x (- x 1))
1.2.4. Functions and Special forms for repeatation
- dolist
- dotimes
- do, do*
- loop
- mapc, mapcar
- some, every
- find, reduce, remove
- member
- count
- delete
- position
- substitute
- recursion
1.2.5. Other special forms
progn
, can be used to evaluate a sequence of forms and return the value of the last one.
Not used very much, probably only needed in 3 places'x
for(quote x)
#'f
for(function f)
- trace and untrace
return
can be used to break out of a block of code
1.2.6. Macro
4 steps to write macro:
- Decide if the macro is really necesary.
- Write down the syntax of the macro.
- Figure out what the macro should expand into.
- Use
defmacro
to implement the syntax/expansion correspondence.
1.2.7. Backquote notation
A backquote indicates that what follows is mostly a literal expression but may contain some components that are to be evaluated. Anything marked by a leading comma ,
is evaluated and inserted into the structure. And anything marked with a leading ,@
must evaluated to a list that is spliced into the structure: each element of the list is inserted, without the top-level parameters.
(setf test1 '(a test)) `(this is ,test1) `(this is ,@test1) `(this is . ,test1) ;; In the middle of a list, only ,@ is a possibility. `(this is ,@test1 -- this is only ,@test1)
1.3. Functions on Lists
- first
- second
- third
- nth
- rest
- car
- cdr
- last
- length
- reverse
- append
- list
- list*
- null
- listp
- consp
- equal
- sort
- subseq
1.3.1. Dotted pair notation
(cons a b)
- When b is not a list. The result is an object x such that (first x) => a and (rest x) => b and where x prints as (a . b).
- When b is a list, the usual list notation is used for output rather than the dotted pair notation.
Either notation can be used for input.
A cons cell is a data structure with two fields: a first and a rest. All proper lists have a last cons cell whose rest field is nil.
1.4. Equality and internal representation
1.5. Functions on sequences
1.6. Functions for maintaining tables
1.6.1. Association table
The association list (a-list) is a type of list used to implement tables. An association list is a list of dotted pairs, where each pair consists of a key and a value.
(setf state-table '((AL . Alabama) (AK . Alaska) (AZ . Arizona) (AR . Arkansas))) (assoc 'AK state-table) (rassoc 'Arizona state-table)
But, dotted pairs could also be normal list.
(setf state-table '((AL Alabama) (AK Alaska) (AZ Arizona) (AR Arkansas))) (assoc 'ar state-table) ;; this does work (rassoc 'Arizona state-table)
Notice: Search the table by value rather than by key doesn’t work for normal list.
1.6.2. Hash table
- make-hash-table
- gethash, retrieve the value associated with a given key.
1.6.3. Property list
A property list (p-list) is a list of alternating key/value pairs.
It is avoided because we have hash table.
1.7. Functions on trees
- tree-equal
- copy-tree
- subst
- sublis
1.8. Functions on numbers
- random
- expt
- sin
- asin
- min
- abs
- sqrt
- round
rem
(rem 11 5)
1.9. Functions on sets
One of the important uses of lists is to represent sets. There are some functions that treat lists in just that way.
- intersection
- union
- set-difference
- member
- subsetp
- adjoin
Functions on bit vectors and integers:
lists | integers | bit vectors |
---|---|---|
intersection | logand | bit-and |
union | logior | bit-ior |
set-difference | logandc2 | bit-andc2 |
member | logbitp | bit |
length | logcount |
1.10. Destructive functions
Functions has side effect
- nconc
- nreverse
- nintersection
- nunion
- nset-difference
- nsubst
- delete, the destructive version of
remove
.
1.11. 3.11 Overview of data types
1.12. Input/output
1.12.1. Input
- read, it is a complete lexical and syntactic parser. It is used to read and return a single lisp expression.
- read-char, read a single character
- read-line, read everything up to the next newline and returns it as a string.
- open
- with-open-stream
1.12.2. Output
- print
- prin1
- princ
- write
- with-open-file
- terpri
- fresh-line
- format
1.13. 3.13 debugging tools
- trace, untrace
- step
- describe
- inspect
- documentation
- apropos
- break
1.14. 3.14 Antibugging tools
- error
- cerror
- check-type
- assert
- time
1.15. Evaluation
- funcall
- apply
- eval
1.16. 3.16 Closure
Ex01, c is the captured clojure
(defun adder (c) "Return a function that adds c to its argument." #'(lambda (x) (+ x c)))
Ex02, returns a clojure that can be used as representation of a bank accound.
(defun bank-account (balance) "Open a bank account starting with the given balance." #'(lambda (action amount) (case action (deposit (setf balance (+ balance amount))) (withdraw (setf balance (- balance amount))))))
1.17. 3.17 special variables
- lexical variables
By default, Common Lisp variables are lexical variables. They are introduced by syntactic construct like let or defun. - special variables
- A variable is made special by
defvar
ordefparameter
. It is just like global variable except: the global binding can be shadowed by a local binding for that variable.
(defun report () (format t "Counter = ~d" *counter*)) > (report) Counter = 0 NIL > (let ((*counter* 100)) (report)) Counter = 100 NIL > (report) Counter = 0 NIL
A lexical variable has lexical scope and indefinite extent. A special variable has indefinite scope and dynamic extent.
- symbol-value
To set a special variable, the following are equivalent:
- (setf (symbol-value var) value)
- (set var value)
- (setf (symbol-value var) value)
- A variable is made special by
1.18. 3.18 Multiple values
You can write functions of your own that return multiple values using the function values
.
(values 1 2 3)
1.19. 3.19 More about parameters
Consider how could we improve the following function’s signature
(defun math-quiz (op range n) "Ask the user a series of math problems." (dotimes (i n) (problem (random range) op (random range)))) (defun problem (x op y) "Ask a math problem, read a reply, and say if it is correct." (format t "~&How much is ~d ~a ~d?" x op y) (if (eql (read) (funcall op x y)) (princ "Correct!") (princ "Sorry, that's not right.")))
The user of math-quiz has to provide all 3 arguments in order, with op is quoted.
1.19.1. Optional arguments
(defun math-quiz (&optional (op '+) (range 100) (n 10)) "Ask the user a series of math problems." (dotimes (i n) (problem (random range) op (random range)))) (math-quiz) (math-quiz '+ 100 2)
Optional arguments are still position dependent.
1.19.2. Key arguments
(defun math-quiz (&key (op '+) (range 100) (n 10)) "Ask the user a series of math problems." (dotimes (i n) (problem (random range) op (random range)))) (math-quiz :n 5) (math-quiz :op '+ :n 5 :range 100)
- A symbol starting with a
:
is called a keyword. - Keywords are constant, and cannot be used as names of variables.
1.19.3. Summary
Key vs optional parameters
key optional (math-quiz :op ’+ :n 5 :range 100) (math-quiz ’+ 100 2) not fixed order (very useful) fixed order - Notice:
&rest
are used to collect a variable number of arguments. Usually, it is used after&key
oroptional
parameters.
- Notice:
- Among the build-in functions, there are two common group of keywords:
:test
,test-not
,key
, for matching functions. Including
- sublis
- position
- subst
- union
- intersection
- set-difference
- remove
- remove-if
- subsetp
- assoc
- find
- member
Notice:
:key
is used to provider a selector function such that the comparison could be make against some part of the object.
- sublis
:start
,:end
,:from-end
, for sequence functions. Including
- remove
- remove-if
- position
- find
- remove
Example of keyword parameter, find-all which find all the items matching a condition in the list.
(defun find-all (item sequence &rest keyword-args &key (test #'eql) test-not &allow-other-keys) "Find all those elements of sequence that match item, according to the keywords. Doesn't alter sequence." (if test-not (apply #'remove item sequence :test-not (complement test-not) keyword-args) (apply #'remove item sequence :test (complement test) keyword-args))) (find-all 1 '(1 2 3 1 1 2 3 4 5)) (remove 3 '(1 2 3 4 5 6) :test #'>) (remove 3 '(1 2 3 4 5 6) :test #'<=) ;; #'> 's complement (remove 3 '(1 2 3 4 5 6) :test #'(lambda (&rest args) (not (apply #'> args))))