UP | HOME
Land of Lisp

Zhao Wei

How can man die better than facing fearful odds, for the ashes of his fathers and the temples of his Gods? -- By Horatius.

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:

  1. Decide if the macro is really necesary.
  2. Write down the syntax of the macro.
  3. Figure out what the macro should expand into.
  4. 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)

  1. 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).
  2. 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 or defparameter.
    • 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)

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 or optional parameters.
  • Among the build-in functions, there are two common group of keywords:
    1. :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.

    2. :start, :end, :from-end, for sequence functions. Including
      • remove
      • remove-if
      • position
      • find
  • 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))))
    

2. TODO Exercises