Lisp Notes: Part I


* SLIME Mode top

** C-c C-z
switch to REPL
** C-c C-q
closes all open parens at the current point
** C-c C-c
slime-compile-defun: compiles the function in which the point is currently located
** C-c C-l
slime-load-file loads a file into the REPL
** C-c C-k
compile and load file in current buffer
** C-M-q
when point is at begining of function, properly indents the whole function
** C-c M-q
when point is anywhere wihtin a function, properly indents the whole function
** C-c C-d d,
runs slime-describe-symbol [symbol name]
** C-c C-d h
runs the hyperspec lookup.
** C-M-x
evaluates the current top-level form. I think this is a way to get the form in a source file into the REPL
* REPL tips top

** ,
, signals that you are going to issue a command to the REPL.
, help brings up all the commands you can issue to the REPL
** quitting:
type "," then "quit" or "sayoonara"
** compiling files:
(compile-file "file_name.lisp") -- generates a .fasl file
** loading files:
(load "file_name.lisp") (load (compile-file "file_name.lisp")) -- generates a .fasl file
** change current directory of the REPL
type "," then "cd"

* Basic terms top
These notes are drawn from Winston and Horn's "LISP" 3rd edition
** list
has 0 or more elements, bounded by () LISP treats first element as a procedure to carry out on the remaining elements of the list The remaining elements are treated as arguments to the procedure
*** list element
a list element can be either an atom or another list
** atom
indivisible things are atoms, e.g. 27, +, hyphenated-symbol
*** numeric atom, or simply 'number'
2, 2.00 are numbers and treated as atoms.
*** symbolic atom, or 'symbol'
non-numeric atom. e.g. first, hyphenated-symbol, +
*** "symbolic expressions" or "expressions"
both lists and atoms are symbolic expressions
** form
The term "form" is applied to an expression when the interest is in the value of the expression
** binding
allocating space in memory to store the value for a symbol is called binding. Lisp binds symbols as they are encountered.
** assignment
process of storing a value in the memory space bound for a symbol
** evaluation
The process of computing the value of a form. One type of evaluation is returning the value stored in the memory space bound to a symbol.
** Procedure
*** difference between a procedure and a function
all functions are procedures, but not all procedures are functions. A function induces no side-effects. All LISP procedures return a value (even if NIL)
*** primitive and user-defined procedures
primitive = supplied by LISP user-defined = defun
* Chapter 2: Important LISP primitive procedures for lists top

Note that the ' character is a macro which expends to QUOTE(). This prevents LISP from attempting to evaluate the list (remember that LISP attempts to call the first list element as a procedure and the rest of the elements are the procedure's arguments)
** first
returns the first element of the list supplied as an argument
	* (first '(fast computers are nice)
	* FAST

	* (first '((fast computers)(are nice))
	* (FAST COMPUTERS)

	* (first '())
	* NIL
** rest
Returns a the list minus the first element.
	* (rest '(fast computers are nice)
	* (FAST COMPUTERS)

	* (rest '((fast computers)(are nice))
	* (ARE NICE)

	* (rest '())
	* NIL
** car and cdr
This is considere "archaic", replaced in part by first and rest. One should be familiar with it at least because you will encounter it in reading.
car = first
cdr = rest.
No biggie. But the cool thing is that you can combine them into a new primitive by placing "a"s and "d" between "c" and "r": cXXr
an "a" indicates a car procedure. a "d" indicates a cdr procedure.
The limit is cXXXXr. Although I was able to do a caddddr, so there is probably no limit.
cadr => (first (rest '(bob frank joe pete)))
     * FRANK

caddr => (first (rest (rest '(bob frank joe pete))))
      * JOE

Is the following Illegal? Nope.
                   4      3     2     1          1     2   3    4
caddddr => (first (rest (rest (rest (rest '(bob frank joe pete archie damian elliot))))))
	* ARCHIE

(cadddr '(bob frank joe pete archie damian elliot))
	* ARCHIE
*** second, third, fourth,... tenth
these are newer primitive procedures provided by lisp. Use these instead
** setf
Assigns a value to a symbol.
	* (setf ab-list '(a b))
setf does not evaluate its first argument, because this is the symbol to which it is assigning a value. Evaluating that argument would result is simply retrieving the value in the memory space bound to that symbol.
*** setf accepts multiple symbol-value pairs

    * (setf ab-list '(a b)
	    cd-list '(c d))
*** t and NIL are special atoms (and so is pi, and all numeric atoms)
these symbols always evaluate to themselves, and you cannot assign anything to them.
I think pi might be another. Yeah, it is. I cannot assign anything to it, and it evaluates to 3.141592653589793d0 All numbers are the same way.
** cons
creates a new list from an expression and a list.
	* (cons 'foo '(bar bat))
	(FOO BAR BAT)
** append
takes a series of arguments which are lists. Produces a new list which contains the elements of the supplied lists.
      * (append '(a b) '(c d))
      (A B C D)

      * (append '((a b) c) '(d e))
      ((A B) C D)
Remember, all args must be lists.
** list
creates a list from its arguments. Does not run things together.
	* (list 'a 'b 'c)
	(A B C)

	* (list '(a b) 'c)
	((A B) C)
** push
works like setf + cons: adds a new element to front of a list and sets the value of the lists symbol to the new value
   * (push new-element list-symbol)
This changes the list bound to list-symbol by putting new-element at its front, and push returns the modified list value.
In other words:
	* (setf list-symbol '(b c))
   	(B C)

   	* (push 'a list-symbol)
	(A B C)

	* list-symbol
	(A B C)
** pop

takes a symbol bound to a list, removes the first element from the list, and returns the first element from the list.
	* (setf list-symbol '(a b c))
   	(A B C)

	* (pop list-symbol)
	A

	* list-symbol
	(B C)
   
** nthcdr
trims off n elements of a list (starting at the first element). arguments are a number and a list. Returns the modified list. Does not change the binding form list push and pop.
   * (setf abc-list '(a b c)
   * (A B C)
   * (nthcdr 2 abc-list)
   * (C)
   * abc-list
   * (A B C)
** butlast
trims off the last n elements. first arg is the list, second is the number of elements to trim.
   * (setf abc-list '(a b c))
   * (A B C)
   * (butlast abc-list 2)
   * (A)
   * abc-list
   * (A B C)
The second argument is optional because it defaults to 1.
** adding to end of a list

Must use a combination of append and list, since there is no complement to cons. Must use list because append requires all args to be lists.
     * (append abc-list (list e))
** last

accepts a list as an arg, and returns a list with all but last element trimmed off.
Note that doing stuff to the end of a list is computationally expensive.
** length
counts the number of _top level_ elements of a list.
       * (length '(a b c))
       * 3
       * (length '((a b) (c d) e))
       * 3
** reverse
reverses the order of the _top level_ elements of a list. Does not effect the internal order of sub-lists.
** assoc

   * (setf frobnitz '((height .54)(weight 4.4)))
    ((HEIGHT 0.54) (WEIGHT 4.4))
   * (assoc 'height frobnitz)
    (HEIGHT 0.54)
   * (assoc 'weight frobnitz)
    (WEIGHT 4.4)
An a-list or associative list is a list of list where each sub-list has two elements, the first of which is treated as a key. assoc accepts a key and an a-list as arguments and returns the first sub-list whose key matches. If the a-list has more then one instance of the same key, assoc will only ever return the first occurrence.
** Numerical primitives

*** number types: integers, floating-point, and ratios
floating point is created when a "." follows an integer.
	 * 1   ; this is an integer
	 * 1.  ; this is an integer
	 * 1.0 ; this is a float

*** primitive procedures:
standard: + - * / mod
**** float
coerce a ratio into a float. Division with remainder results in a ratio type.
     * (/ 22 7)
     * 22/7
     * (float (/ 22 7))
     * 3.14286
**** round
accepts a ratio and returns an integer. Rounds half even. Actually, returns the nearest integer AND the remainder.
     * (round 22/7)
     * 3
     * 1/7
**** MAX, MIN
takes any number of args, returns the min or max
**** EXPT, SQRT
expt takes two args -- a number, and the power to which the first arg is to be raise. Can be floats
sqrt finds the root of its argument, and will return a complex number
**** ABS, FLOOR, CEILING
These take one argument and do what you expect. Floor and ceiling return two values (like round), the second of which is the fractional differenc between the input value and the output value.
     * (ceiling 2.4)
     * 3
     * -0.5999999

* Chapter 3: Procedure Definition and Binding top
** problems (horn & white)
*** 3-1

(defun exchange (sinners)
       (reverse sinners))

** Functions

Parameters have lexical scope -- bind values into symbols in the scope of the function.
The value of the last form is returned from the function
*** Lexical variable
function parameters are lexical variables
*** Special variable
is special if appears in a function in which it is not a parameter.
*** LET

   (let ((param_1 init_value)
	  ...
	 (param_n init_value))
	 _forms_ )
The initial value forms are said to be evaluated in parallel. This means that you cannot assign the value of param_1 to param_2. e.g:
     * (setf x 'outside)
     * (let ((x 'inside) ;; x's paramter value will be INSIDE
	     (y x)	 ;; y's paramter value will be OUTSIDE
	     (list x y))
     * (INSIDE OUTSIDE)
*** LET*
This evaluates parameter values in series, so that you can assign the value of one parameter to another. e.g:

     * (setf x 'outside)
     * (let ((x 'inside) ;; x's paramter value will be INSIDE
	     (y x)	 ;; y's paramter value will be INSIDE
	     (list x y))
     * (INSIDE INSIDE)

* Chapter 4: Predicates and Conditionals top

** Predicate: procedure that returns true or false
False is always NIL. True is anything else, but t or T is idiomatic.
** Equality

Mnemonic for remembering equality functions:
EQ is the most primitive check (hence smallest name) while EQUAL is the most sophisticated, literate check, hence the fullest name; EQL being in the middle checks numerical value.
Note that these functions all short-circuit by delegating to the more primitive (and less expensive) check first. In this way, EQUAL essentially checks for address equality, then numerical equality, then lastly expression value (form) equality.
Note the difference between EQL and =. (EQL 1.0 1) is nil because the two number are different types. (= 1.0 1) is T.
*** EQ
test if args point to same memory address. Identical symbols will have same address.
*** EQL
tries EQ, then if numbers, tests if same type and value
*** EQUAL
test two args to see if their values are the same. Works on atoms and lists First tries EQL
*** =
test if args represent the same number (even if different types)
** MEMBER
tests an arg for membership in a list
   * (setf sentence '(tell me more about your mother please))
   * (member 'mother sentence)
   (MOTHER PLEASE)
uses EQL, but can use other predicates
   * (setf pairs '((maple shade) (apple fruit)))
   * (member '(maple shade) pairs)
   NIL
   * (member '(maple shade) pairs :test #'equal)
   ((MAPLE SHADE)(APPLE FRUIT))
** #'
in #'equal, equal is a procedure name. #' is a macro to retrieve the procedure object of the given name #' is short for function #'equal is the same as (function equal)
** Predicates to test object data types

*** atom
is it an atom?
*** numberp
is it a number
*** symbolp
is it a symbol, a non-numeric atom?
*** listp
is it a list?
** NIL is equivalent to the empty list, ()

   * (listp nil)
   T
** List Predicates

*** null
is empty list?
*** endp
is empty list? Unlike null, will error if arg is not a list
** Number predicates
*** numberp
*** zerop
*** plusp
*** minusp
*** evenp
*** oddp
*** >
are they in descending order?
*** <
are the in ascending order?
*** <=
in ascending order, adjacent equal symbols don't fail the test
   * (<= 4 5 6)

   T
   * (<= 4 5 5)

   T
** Excercise 4-1
the rem function takes two numeric params, and returns the remainder of division of the first by the second.
   * (defun divisible-by-three (n)
       (= 0 (rem n 3)))
** Excercise 4-2

(defun palindromep (list)
	   (equal list (reverse list)))
** Excercise 4-3
Tests for right triangle by testing if sum of the squares of short side within 2% of the square of the long side. First arg is assumned to be the long side.
(defun rightp (a b c)
       (<= (* a a 0.98) (+ (* b b) (* c c)) (* a a 1.02)))
** Logical Predicates

Both AND and OR evaluate from left to right and short-circuit.
*** AND
returns NIL if any of its arguments are NIL. Note that the value of the last argument is returned.

*** OR
return NIL when all of its arguments are NIL Note that the first non-NIL value is returned by this expression.

*** NOT
Turns NIL values into T, and not-nil values into NIL. The "NIL complement"
** Conditional Branching

*** IF
This works like the ternary operator:
	 (if <test> <then form> <else form>)

    * (if (symbolp 'dog) 'arf 'meow)
    ARF
*** WHEN

    (if <test> <then form> nil) 
is equalivalent to
    (when <test> <then form>)
Note that <then form> can be any number of expressions
*** UNLESS

    (if <test> nil <else form>)
is equilvalent to
    (unless <test> <else form>)
Note that <else form> can be any number of expressions
** Problem 4-5
Write IF forms that are equivalen to (ABS X), (MIN A B), and (MAX A B)

 *  (defun my-abs (x)
        (if (< x 0) (* -1 x) x))

 * (defun my-min (a b)
        (if (< a b) a b))

 * (defun my-max (a b)
        (if (> a b) a b))
*** COND

    (COND (<test 1> <consequent 1-1> ...)
          ...
     	  (<test n> <consequent n-1>...))
Tests each condition, until one is found which is T, then evaluates all the consequent forms associated with the successful test. The value return is the value of the last triggered consequent (preceding triggered consequents are there for their side-effects).

A standard practice is to include a final clause whose test is simply T to prevent falling through the COND form and returning NIL.
    * (setf x 0)
    * (COND ((> x 1) (/ x x))
            ((= x .5) (* x x))
	    (t x))

** Problem 4-6
Compose COND forms that are equivalent to (NOT U) (OR X Y Z) (AND A BB C)
   * (defun my-not (u)
       (cond ((equal nil u) t)
             (t nil)))
   
   * (defun my-or (a b c)
        (cond ((not (equal nil a)) a)
              ((not (equal nil b)) b)
              ((not (equal nil c)) c)))
   
   * (defun my-and (a b c)
        (cond ((equal nil a) nil)
              ((equal nil b) nil)
              ((equal nil c) nil)
	      (t c)))
*** CASE
The CASE function is like the switch operator in other languages.
    (case <key form>
    	  (<key 1> <consequent 1-1> ...)
	  ...
	  (<key n> <consequent m-1> ...))

The <key form> is evaluated and compared to each unevaluated key using EQL, executing the consequent of the first matching key.
The last key may be simply T or OTHERWISE to provide a default case.
The <key form> is evaluated, and so can be a variable. The <key n> is NOT evaluated, however.
       * (setf thing 'dog)
       * (case thing
       	       (dog 'arf)
               (cat 'meow))
	
      	 ARF
The <key n> can be a list. When a key is a list, then MEMBER is used to test if <key form> is a member of the key list.
* Chapter 5: Procedure Abstraction and Recursion top
** Singlely recursive
A function in which each call can generate only one branch in which it calls itself. This is considered to be not strictly recursive because it can easily be rewritten to not be recursive.

   (defun count-elements (1)
      (if (enpd l)
          0
	  (+ 1 (count-elements (rest l)))))

** Fibonacci

(defun fibonacci (n)
	   (if (or (= n 0) (= n 1))
	       1
	       (+ (fibonacci (- n 1))
		  (fibonacci (- n 2)))))
** Tail Recursion
"Whenever a problem is converted into a new problem such that no further compuation is necessary once the new problem is solved, the new problem is said to be a reduction of the original problem. Whenever a recursive procedure is defined such that all recursive calls to itself are reductions, that procedure is said to be tail recursive."
(defun count-elements-cleveryly (l)
  (count-elements-cleverly-aux l 0))

(count-elements-aux (l result)
  (if (endp l)
      result
      (count-elements-cleverly-aux (rest l) (+ 1 result))))
This is different because the singly-recurive count-elements above returns a computation on the result of the recursive call to itself.
   (defun count-elements (1)
      (if (enpd l)
          0
	  (+ 1 (count-elements (rest l)))))
** Problem 5 -1

;; write a tail-recursive procedure skip-first-n which
;; trims off the first n elements of a list

(defun skip-first-n (list n)
  (if (<= n 0)
      list
    (skip-first-n (cdr list) (1- n)))))
** Problem 5-2

;; non-tail recursive function to keep the first n
;; elements of a list; we may assume there are at least n elements

(defun keep-first-n (list n)
  (keep-first-n-aux list n ()))

(defun keep-first-n-aux (l n result)
  (if (= 0 n)
      result
    (keep-first-n-aux (cdr l) (1- n) (append result (list (car l))))))

WRONG! correct:

(defun keep-first-n (n l)
  (if (zerop n)
      nil
      (cons (first l) (keep-first-n (- n l) (rest l)))))
** Recursion can be used to analyze nested expressions

;; count (possibly nested) atoms in a list
(defun count-atoms (input)
  (if (endp input)
      0
    (if (atom (car input))
	(+ 1 (count-atoms (cdr input)))
      (+ (count-atoms (car input)) (count-atoms (cdr input))))))

;; write ADD for two (positive) numbers using only 1+ and 1-
(defun add (a b)
  (if (= 0 b)
      a
    (add (1+ a) (1- b))))

;; presentp: determines whether an atom occurs anywhere in an expression
(defun presentp (l expression)
  (if (endp l) 
      nil
    (cond ((listp (car l)) (or (presentp (car l) expression) (presentp (cdr l) expression)))
	  ((atom (car l)) (or (equal (car l) expression) (presentp (cdr l) expression))))))
** Optional parameters: eliminate aux functions
optional parameter &optional (x default value x-supplied-p
;;optional parameters example

(defun greet-couple(name &optional (other "funny little person" other-supplied-p))
  (cond 
   (other-supplied-p 
    (format t "Hello, ~a and ~a" name other))
   (t
    (format t "Hello, ~a -- and you too, ~a" name other)))) 
** Rest parameters

(defun raise (x &rest numbers)
   (raise-aux x numbers))
any number of symbols following after &rest are treated as parameters.
** Key or keyword parameters
Allow a parameter value to be "tagged" so that order of supplying them is not important. An example invocation looks like:
(rotate '(a b c) :direction 'left)

(defun rotate (input-list &key direction)
  (if (equal direction 'left) ...))
When not explictly supplied in the invocation, the keyword is bound to nil. You can, however, specify a default value.
(defun rotate (input-list &key (direction 'right))
  (if (equal direction 'left) ...))

** AUX parameters &aux
These are not matched to any arguments at all. They are "LET* parameters in disguise"
The following are equivalent
(defun both-ends-with-let (whole-list)
   (let* ((element (first whole-list))
          (trailer (last whole-list)))
     (cons element trailer)))


(defun both-ends-with-aux
       (whole-list &aux
                   (element (first whole-list))
		   (trailer (last whole-list)))
  (cons element trailer))

* Chapter 6: Data Abstraction and Mapping top

** goals
Data abstraction allows building large, complicated programs.
Using recursion to carry out computation on each list element
Programming cliches are templates for programming tasks. Some are built into our languages. Examples are transforming, filtering, counting, and finding.
lambda expression
** Mapping primitives
MAPCAR REMOVE-IF REMOVE-IF-NOT COUNT-IF FIND-IF
Mapping is considered a control strategy.
** Use readers, constructors, writers
shield logic from structure of the data
Create a function to construct a data object, one to read that object, and another to write it. This shields the rest of the app from changes to how that data is structured or future changes to it.
** Transformation cliche

(defun <transforming procedure> (input list)
  (if (endp input-list)
      nil
      (cons (<element transformer> (first input-list)) ;Transform
            (<transforming procedure> (rest input-list))))) ;Recurse
** Filtering cliche

(defun <filtering procedure> (input-list)
  (cond ((endp input-list) nil)
        ((<element tester> (first input-list))
         (cons (first input-list)
               (<filtering procedure> (rest input-list))))
	(t (<filtering procedure> (rest input-list))))) 
** Counting cliche

(defun <counting procedure> (input-list)
  (cond ((endp input-list) 0)
        ((<element tester> (first input-list))
  	 (+ 1 (<counting procedure> (rest input-list))))
	(t (<counting procedure> (rest input-list)))))
** finding cliche

(defun <finding procedure> (input-list)
  (cond ((endp input-list) nil)
        ((<element tester> (first input-list))
         (first input-list))
	(t (<finding procedure> (rest input-list)))))
** MAPCAR

   * (mapcar #'oddp '(1 2 3))
   (T NIL T)

   * (mapcar #'= '(1 2 3) '(3 2 1))
   (NIL T NIL)
The number of lists supplied to mapcar should be equal to the number of parameters taken by the test procedure. In the second example, the comparisons are between
	    1 3
	    2 2
	    3 1
** REMOVE-IF and REMOVE-IF-NOT

   CL-USER> (remove-if #'oddp '(1 2 3))
   (2)
   CL-USER> (remove-if-not #'oddp '(1 2 3))
   (1 3)
** COUNT-IF and COUNT-IF-NOT

   CL-USER> (count-if #'oddp '(1 2 3))
   2
   CL-USER> (count-if-not #'oddp '(1 2 3))
   1
** FUNCALL and APPLY

   (funcall #'<procedure specification>
            <arg 1>
	    ...
	    <arg n>)
The term "funargs" refers to a function parameter which is a procedure.
We can use procedures as parameters to our own functions.
    CL-USER> (defun toss (argument procedure)
    	   (funcall procedure argument))
    TOSS
    CL-USER> (toss '(a b c) #'first)
    A
    CL-USER> (toss '(a b c) #'last)
   (C)
LISP does not evaluate the first element in a form; rather it uses it as the name of a procedure to look up and run.
** APPLY

   (apply #'<procedure name> <list args>)
APPLY uses its first argument's value on the elements of its second argument's value, which must be a list. This list has as many elements as the <procedure name> requires.
This is different than funcall in that funcall has as many parameters as its procedure argument requires.
Apply would then seem to let you abstract out the call to any function using parameters representing the function name and a list of parameters to use; therefore the signature of all calls to apply are identical.
   CL-USER> (apply #'first '((a b c d)))
   A
** LAMBDA functions: anonymous procedures

Just like a defun form, just replace defun with lambda and drop the name of the form, for instance:
   (lambda (input) 
      (cons (first input) (last input)))


      CL-USER> (mapcar #'(lambda (input)
      		     (cons (first input) (last input))) 
               '((a b c) (d e f) (g h i)))
      ((A C) (D F) (G I))

* Chapter 7: Iteration on Numbers and Lists top

Iteration primitives:
DOTIMES: iterates n times DOLIST: iterates over a list DO: more general iteration primitive
** DOTIMES

(dotimes (<count parameter> <upper-bound form> <result form>)
   )
First, on entry, <upper-bound form> is evaluated to value n. Then, for each value from 0 to n - 1: The value is assigned to <count parameter>. The body is executed.
When this is complete, the binding for <count parameter> is eliminated and the <result form> is evaluated, which is the value returned by dotimes.
*** Count parameter goes from 0 to n - 1

  CL-USER> (defun show-count (n)
	     (dotimes (i n)
	        (format t "current increment is ~a (~R) ~%" i i)))
  SHOW-COUNT
  CL-USER> (show-count 5)
  current increment is 0 (zero) 
  current increment is 1 (one) 
  current increment is 2 (two) 
  current increment is 3 (three) 
  current increment is 4 (four) 
  NIL

*** Problem 7-1

(defun dotimes-factorial (n)
  (let ((result n))
    (dotimes (count n result)
      (setf result (if (= 0 count) (* 1 result) (* count result))))))


** DOLIST
Like dotimes except here, each member of <list form> is assigned to <element parameter> upon each iteration.
(dolist (<element parameter> <list form> <result form>)
  )
*** Example

(setf freezing 32 boiling 212)

(defun count-outlyers (list-of-elements)
  (let ((result 0))
    (dolist (element list-of-elements result)
      (when (or (> element boiling)
		(< element freezing))
	(setf result (+ result 1))))))
DOLIST is often used to invoke side-effects, rather than to map, search, filter, or transform a list.
** Breaking out of DOTIMES and DOLIST

When a call to (return <expression>) is encountered in the body of the dolist or dotimes, <expression> is returned as the value of the dolist or dotimes.
** DO

This primitive can do what both dotimes and dolist do. A return state can also break out of a do iteration.
(do () ;; a list of pairs (var1 val) (var2 val)
    (<test> <return>)   ;; condition to terminate loop and what to return
    )             ;; body to execute on each iteration
*** a silly example

(defun count-down-by-two (n)
  (do ((count n) (sum 0))((< count 0) sum)
    (format t "~a~%" count)
    (setf count (- count 2))
    (setf sum (+ count sum))))

*** More complete template

(do ((<parameter 1> <initial value> <update form 1>)
     ...
     (<parameter n> <initial value> <update form n>))
    (<terminaltion test> <intermediate forms, if any> <result form>)
    )
The <update form *> is evaluated and assigned to the parameter on each iteration.
Any number of <intermediate forms> can follow the <termination test>, but are only evaluated when the termination test is not NIL. The last form here (<result form>) is returned when the terminationtest is not NIL.
Do handles its parameters in parallel, so it is like LET in this regard.
** DO*
This is exactly like DO, but handles its parameters serially, rather than in parallel.

*** problem 7-7: define do-factorial using a DO form with an empty body

(defun do-factorial (n)
  "I cheated and used a do* form instead"
  (do* ((count n (1- count))
       (result 1 (if (zerop count) (* 1 result) (* count result))))
      ((zerop count) (* n result))))
** LOOP

(loop )
loop executes its body until a return statement is executed.
(setf cheers '(cheer cheer cheer))
(setf loop-count 0)

(loop
  (when (endp cheer) (return loop-count))
  (setf cheers (rest cheers))
  (setf loop-count (+ loop-count 1)))
Watch out for infinite loops!
** PROG1 and PROGN
These are forms which sequentially evaluate an arbitrariliy long series of forms and return as the value of the prog* form either the first (prog1) or the last (progn) form.
   CL-USER> (prog1 (+ 1 0) (+ 2 0) (* 1 3))
   1
   CL-USER> (progn (+ 1 0) (+ 2 0) (* 1 3))
   3
** How to choose the right control stategy
If the mathematical function being implemented suggests one, use it.
*** Recursion
when "solving a problem involves dividing into an expression" (not just looking at list elements)
*** MAPCAR, REMOVE-IF* COUNT-IF* FIND-IF*
when the problem involved transforming or filtering a list, or counting or finding.
*** DOLIST, DOTIMES, DO
when a problem requires iteration

* Chapter 8: File Editing, Compiling, and Loading top
strings, ed, load, compile-file
** ED

   (ed ) 

This primitive "...takes you from lisp and puts you in an editor".
** LOAD

      (load )

This primitive evaluates all the forms in the file into lisp. This is basically as though you typed it in -- actually input is redirected from the REPL to the file when it is being loaded.
You can also use load to load compiled files as well.
** strings
A string is a LISP data type constituted by a sequence of characters delimited by double quote. For example:
"The quick brown fox jumps over the lazy dog."
   CL-USER> "The quick brown fox jumps over the lazy dog."
   "The quick brown fox jumps over the lazy dog."
   CL-USER> 
Note that case is conserved when LISP evaluates the string.
Files are specified by strings.
** COMPILE-FILE
(compile-file )
Rather than loading the file into the interpreter (where the source is evaluated every time a function is invoked), the file is compiled into machine instructions, which are then executed.

** COMPILE

   (compile <procedure name>)
You can compile a procedure you have already defined using this primitive.

* Chapter 9: Printing and Reading top

** PRINT
This primitive takes a single argument and prints it to the screen.
   CL-USER> (setf temp 100)

   100
   CL-USER> (print temp)

   100  <-- this is the result of print's action
   100  <-- this is the value of the print form
The fact that print both produces a side-effect and and evaluated value means that you can use it within other expressions:
   * (if (< -1 (print (- temperature 98.6)) +1)
     	 'normal
	 'abnormal)
The argument to print can be any expression, not just a symbol.
** READ
This primitive blocks untill a line of input is entered into LISP.
     CL-USER> (read)
     "More books"  <-- input typed into the console
     "More books"  <-- evaluation of what was read
You can assign this value to something of course.
    CL-USER> (defun spell-number-prompt ()
        	   (let ((n nil))
	   	     (print '(enter a number))
	     	     (setf n (read))
	     	     (format t "~R ~%" n)))
    SPELL-NUMBER-PROMPT
    CL-USER> (spell-number-prompt)

    (ENTER A NUMBER) 1024
    one thousand twenty-four 
    NIL
** FORMAT

   CL-USER> (format t "Hello, world!")

   Hello, world!
   NIL
The "t" stands for terminal, and indicates that this procedure should print out to the terminal. In place of "t" could be a symbol to connect this method to print to a file.
*** FORMAT Directives
The tilde "~" introduces a directive which controls the formatting.

% newline & newline, but does nothing if already at start of newline. This would be used when wanting to ensure to start printing on start of new line, but unsure whether currently already at a start of line (maybe some other directive ended with a new line)
 
    CL-USER> (format t "huh?~%~%huh?~%~&")
    huh?
    huh?
    NIL

a aesthetic, interpolates a value into the string, nicely. Must be one argument after the string for each occurance of this directive.
 
     CL-USER> (format t "I'm thinking of a number from ~a to ~a" 1/3 1024.5)
     I'm thinking of a number from 1/3 to 1024.5
     NIL
This directive can also be preceeded with a number to indicate padding, as when making a tabular display:
 
	CL-USER> (format t "I'm thinking of a number from ~6a to ~6a" 5 34567)
	I'm thinking of a number from 5      to 34567 
	NIL
	CL-USER> (format t "I'm thinking of a number from ~6a to ~6a" 534667 34567)
	I'm thinking of a number from 534667 to 34567 
	NIL

There are many, many more features to format.
** WITH-OPEN-FILE
Lisp I/O is based on streams.
Input streams are associated with READ forms. Output streams are associated with PRINT or FORMAT forms.
The with-open-file macro creates an input or output stream from a file specification, and binds that stream to a specified name. The prototype:
	(with-open-file (<stream name> <file spec> :direction <:input or :output>)
	   ...do stuff )
The keyword argument :direction serves to signal the presence of the next argument :input
	CL-USER> (with-open-file (out "/home/grantham/out.tmp" :direction :output)
        (format out "(Hello file!)"))
	NIL
	CL-USER> (with-open-file (in "/home/grantham/out.tmp" :direction :input)
	  	   (print (read in)))

	(HELLO FILE!) 
	(HELLO FILE!)
	CL-USER> 
** EOF detection on reading
passing NIL as a second parameter to READ tells it to return nil when EOF is reached. Otherwise, it raises an error.
       CL-USER> (with-open-file (out "/home/grantham/out.tmp" :direction :output)
	 	  (dotimes (n 4)
	     	    (format out "(line ~R)~%" n)))
        NIL
	CL-USER> (with-open-file (in "/home/grantham/out.tmp" :direction :input)
	   	   (do ((record (read in nil)(read in nil)))
	               ((not record))
	             (print record)))
			   
       (LINE ZERO) 
       (LINE ONE) 
       (LINE TWO) 
       (LINE THREE) 
       NIL
       CL-USER> 
*** Encountering NIL before EOF

    	     CL-USER> (with-open-file (out "/home/grantham/out.tmp" :direction :output)
	     	        (dotimes (n 4)
	     		  (format out "NIL")(format out "(line ~R)~%" n)))
	     NIL
	     CL-USER> (with-open-file (in "/home/grantham/out.tmp" :direction :input)
	                (do ((record (read in nil)(read in nil)))
	       		    ((not record))
	     		  (print record)))
	     NIL
	     CL-USER>
But if we change the reader to also check for EOF, we can read the whole thing.

** EVAL

EVAL evaluates its arguments and then evaluates the results.
	CL-USER> (setf form-to-evaluate '(+ 2 2))
	(+ 2 2)
	CL-USER> (eval form-to-evaluate)
	4
Is said to evaluate its arguments twice.
   CL-USER> (defun my-sum(a b c)
	      (list '+ a b c))
   MY-SUM
   CL-USER> (eval (my-sum 1 2 3))
   6
** Strings and Sequence Data Types
LENGTH, REVERSE, and ELT work on both lists and Strings (because they are both Sequence Data Types).
*** ELT
Stands for ELemenT. Returns the element at the specified (0-based) index.
       CL-USER> (elt '(a b c d) 1)
       B
       CL-USER> (elt "abcd" 1)
       #\b
       CL-USER> 
Character objects are printed as "#/[.]"
** STRING= and STRING-EQUAL
These primitive work only on strings
STRING= is case sensitive STRING-EQUAL is not case sensitive
       CL-USER> (string= "abcd" "ABCD")
       NIL
       CL-USER> (string-equal "abcd" "ABCD")
       T
       CL-USER> 
** CHAR= and CHAR-EQUAL
These primitive work only on characters.
CHAR= is case sensitive CHAR-EQUAL is not case sensitive
       CL-USER> (char= #\a #\A)
       NIL
       CL-USER> (char-equal #\a #\A)
       T

** SEARCH
This primitive works on sequences. Returns a 0-based index of the match.
(search <sequence-search-term> <sequence-to-search-in>)

     CL-USER> (search '(c) '(a b c d))
     2
     CL-USER> (search "bc" "abcd")
     1
To reiterate: SEARCH works on *SEQUENCES*. That is why this doesn't work:
	CL-USER> (search #\d "abcdefg")
but this does
    	 CL-USER> (search '(#\d) "abcdefg")
	 3
OR
    	 CL-USER> (search "d" "abcdefg")
	 3
Note that you get results you probably didn't intend by this
    CL-USER> (search '(d) "abcdefg")
    NIL
This is because the sequence we are searching in is a string, a sequence of characters. Therefore our search argument must be a sequence of the same type.

** READ-LINE and READ-CHAR
READ-LINE returns two values. The first is the string read, up to a carriage return or EOF. The second value is NIL, indicating a new line was encountered, or T, indicating EOF was reached.
    CL-USER> (read-line)
    This is a line of text, and I'm gonna hit return right now
    "This is a line of text, and I'm gonna hit return right now"
    NIL
READ-CHAR reads one char from input.
     CL-USER> (read-char)
     assddasdasd
     #\a
Both READ-LINE and READ-CHAR take the same two optional arguments that READ does: 1) An input stream 2) Nil - returns nil at EOF (rather than raising an error).

* Chapter 10: Rules for Good Programming and Tools for Debugging top

** Use comments and descriptive function, parameter, and variable names
** Procedures should depend as little as possible on the external state of the application
A procedure should either avoid depending on a particular external state, or explicity test for the required state and handle itself if not in that state. Example: the block-worlds app put-on function should first check if there is space available, if not attempt to clear some space, then place the block.
** Procedures should report on what is going on when they encounter unexpected situations.
Again, in the block-world example, if put-on can't get space, it returns nil after printing an explanatory message.
** Use procedure and data abstraction
Decompose a big function into smaller, reusable ones. Use readers and writers for accessing and persisting data, rather than interacting with the raw data structure. Build related functional groups of code (increase cohesion).
Limiting the dependency paths into and out of your module makes for a clean interface (decrease coupling).
** Make programs modular.
Generally each module exists in a single file, the couplings is reduced going out and there is internal cohesion regarding the concern of the code.

** Debugging primitives: TRACE, STEP, BREAK, TIME, DESCRIBE, DRIBBLE
Trace is used often, step never, break occaisionally.
*** TRACE
Causes entry and exit information for the procedures supplied as arguments.
To shut this off, call UNTRACE passing in zero or more function names. When no function names are passed in, then this disables TRACE for everything. Calling TRACE with no parameters does nothing but return nil.
Indentation and numbers show the level of recursion.
**** TRACE example:

CL-USER> (defun count-atoms (expression)
	   (cond ((null expression) 0)
		 ((atom expression) 1)
		 (t (+ (count-atoms (car expression))
			 (count-atoms (cdr expression))))))

CL-USER> (trace count-atoms)
(COUNT-ATOMS)
CL-USER> (count-atoms '((a b)(c d)))
  0: (COUNT-ATOMS ((A B) (C D)))
    1: (COUNT-ATOMS (A B))
      2: (COUNT-ATOMS A)
      2: COUNT-ATOMS returned 1
      2: (COUNT-ATOMS (B))
        3: (COUNT-ATOMS B)
        3: COUNT-ATOMS returned 1
        3: (COUNT-ATOMS NIL)
        3: COUNT-ATOMS returned 0
      2: COUNT-ATOMS returned 1
    1: COUNT-ATOMS returned 2
    1: (COUNT-ATOMS ((C D)))
      2: (COUNT-ATOMS (C D))
        3: (COUNT-ATOMS C)
        3: COUNT-ATOMS returned 1
        3: (COUNT-ATOMS (D))
          4: (COUNT-ATOMS D)
          4: COUNT-ATOMS returned 1
          4: (COUNT-ATOMS NIL)
          4: COUNT-ATOMS returned 0
        3: COUNT-ATOMS returned 1
      2: COUNT-ATOMS returned 2
      2: (COUNT-ATOMS NIL)
      2: COUNT-ATOMS returned 0
    1: COUNT-ATOMS returned 2
  0: COUNT-ATOMS returned 4
4
CL-USER> (untrace count-atoms)
T
*** STEP
This is implementation dependant. In the Winston and Horn book, the implementation prints each expression and pauses, then when down arrow is entered it is evaluated.
In SBCL, however, it seems it does nothing but evaluate the function.
*** BREAK
A break form is added to the source code as a diagnostic. The REPL will pause at the break and print your message. In slime, pressing "c" will allow you to continue. Supposedly, you can interact at that point and change values, etc. Not sure how to do this in slime.
     CL-USER> (defun break-test (x)
     	         (when (> x 0) (break "x > 0"))
	         (* x x))
     CL-USER> (break-test 0)
     0
     <== in here, we dropped into the debugger in  ==>
     <== slime on the break statement              ==>
     CL-USER> (break-test 1)
     1
*** TIME
This compute how long it takes to evaluate a form.
CL-USER> (time (+ 3 5))
Evaluation took:
  0.0 seconds of real time
  0.0 seconds of user run time
  0.0 seconds of system run time
  0 calls to %EVAL
  0 page faults and
  0 bytes consed.
8
*** DESCRIBE
Prints out infomration about any form.
CL-USER> (setf symbol-example '(a b c))
(A B C)
CL-USER> (describe symbol-example)
(A B C) is a CONS.
; No value

CL-USER> (describe 'break-test)
BREAK-TEST is an internal symbol in #<PACKAGE "COMMON-LISP-USER">.
Function: #<FUNCTION BREAK-TEST>
Its associated name (as in FUNCTION-LAMBDA-EXPRESSION) is BREAK-TEST.
The function's arguments are:  (X)
Its defined argument types are:
  (T)
Its result type is:
  (VALUES
   (OR (MEMBER 0.0d0 0.0) (SINGLE-FLOAT (0.0)) (DOUBLE-FLOAT (0.0d0))
       (RATIONAL 0))
   &OPTIONAL)
On Tue, Mar 25, 2008 12:38:34 PM CDT it was compiled from:
  (LAMBDA ()
    (PROGN
     (SB-INT:NAMED-LAMBDA BREAK-TEST (X)
                          (BLOCK BREAK-TEST
                            (WHEN (> X 0) (BREAK "x > 0"))
                            (* X X)))))

; No value
*** DRIBBLE

(dribble )
This prints out your REPL session to the file specified.
(dribble) this turns off dribbling.