A couple lisp Notes:

default

Links
 
Todo - find all +** and create examples.

*** Some of this may be implementation specific
*** whether clisp, sbcl, etc

The lisp reader translates text into lisp objects.
The lisp evaluator deals with these objects.
In other words the lisp reader can take:
15
30/2
#xf
It will translate these to the same object,
before it reaches the lisp evaluator.

(setq *print-case* :capitalize)
; Sets output to be Capitals instead of default :upcase [:downcase can also be used] 

:q
in case clisp starts acting crazy after a mistake

cntrl-c :a
Exit an infinite loop
:a = abort

:a
abort, when running into error

:bt
backtrace when running into error

(error "oh no! blah blah")
Throw an error on purpose, with a message of "oh no..."


(define-condition omg () ()
  (:report (lambda (condition stream)
             (princ "OMG! Stop screwing up" stream))))
(error 'omg)
Create a custom condition and trigger it with error.


(defun screwed-function ()
  (error 'omg))
(handler-case (screwed-function)
  (omg () "Don't bother me!")
  (oh-yeah () "Call me any time."))
Intercept condition with a 'handler-case', this
stops the REPL from erroring out, and let's the
program keep running.

(unwind-protect (/ 1 0)
  (princ "Even dividing by zero can't stop me! buhaaahahaha"))
Use 'unwind-protect' to execute crucial code even after an
error was aborted.

*
Is set to the last evaluation [last returned value]
(print "test")
*
Would evaluate to "test" [returns "test"]

(directory "./")
Show current working directory in clisp

(directory "./*")
List files in current working directory

(ext:dir)
Show files in current working directory in clisp (name, size, date created) 

(load "chosen-file.cl")
Load a file into clisp interpreter

clisp -i chosen-file.cl
clisp -init-file chosen-file.cl
Loads files at startup

(compile-file "chosen-file.cl")
Compile file from inside lisp [fas file must be loaded afterwards]
(load "chosen-file.fas")

clisp -c file-name.cl
Compile lisp file

(compile 'this-function)
A defined function in the interpreter can be compiled, by
giving it's name

#||
Multiline comment in your face
||#

;
is a comment

;;
Comment for code that follows and is indented
the same as the code, like in the body of
a function or macro

;;;
Comment that is a paragraph explaining a
large amount of code

;;;;
File header comment (for describing your file)

(sleep 20)
Sleep for 20 seconds

(sleep (* 1 60))
Sleep for one minute

(defun sleep-minutes (m)
  (sleep (* m 60))
(sleep-minutes 2)
Define a sleep function and use it to sleep for 2 minutes.

(defun add-em-up (x y)
  "Add two numbers, it's fun"
  (format t "Wow adding ~d plus ~d is great!!.~%" x y)
  (+ x y))
Example of using a documentation string. [the second line]
That can be called like below. Acts as a comment to
describe the function.

(documentation 'add-em-up 'function)
(documentation 'defun 'function)
Display the documentation string of a function.

*global-variable*
*..* is used to represent variables

+constant+
+..+ is used for constants

%low-level-function%
%%low-level-function%%
%..% and %%..%% used for low level functions
These naming convetions are not required but many
use them.

-
Used to seperate two words compouned as a function, variable
or macro name, as in happy-days.

->
Functions that convert one kind of value to another
use -> in the name, instead of a -


"hello, world"
(format t "hello, world")
(write-line "hello, world")
(print "hello, world")
Hello worlds
Print prints out in a form that can be read by the lisp reader

(defun hello-world () (format t "hello, world"))
Hello world function

(defun kitty
  (color nickname &optional size cool-or-not)
  (list color nickname size cool-or-not))
(kitty "orange" "morangki")
(kitty "black" "blacki" "little")
(kitty "brown" "beaki" "fluff" "annoying")
Function with optional parameters, the first two
are required, the 3rd and 4th are optional.

(defun virgins (&optional (a "mary") b) (list a b))
(virgins "lilith")
(virgins "daiquiri" "pina colada")
Optional parameter with default value if left out
when calling the function.

(defun bootie-call (backup-bootie &optional (new-bootie backup-bootie))
  (list backup-bootie new-bootie))
(bootie-call "ariana" "taizya")
(bootie-call "ariana")
Use the first parameter as the default to the second,
if the second one is not supplied.

(defun meals-today (bfast lunch &optional (dinner "torta" dinner-supplied-p))
  (list bfast lunch dinner dinner-supplied-p))
(meals-today "pigeon egg" "rat sandwich" "opossum steak")
(meals-today "armadillo eggs" "kangaroo toes")
Blah-blah-supplied-p will return true if arguement is supplied,
otherwise it returns NIL, revealing that the default
value was used.

call-arguments-limit
Will shows how many options your lisp
implementation will allow

(defun girlfriends (&key suckass so-so good oh-yes)
       (list suckass so-so good oh-yes))
(girlfriends :oh-yes "kat")
(girlfriends :oh-yes '("kat" "megan"))
(girlfriends :suckass "sarah" :so-so "beth" :good "nadjmeh" :oh-yes "kat")
Keyword parameters, let you set value by :keyword

(defun love-is (&key (a "over")
                     (b "imagined" b-supplied-p)
                     (c (concatenate 'string a b)))
  (list a b c b-supplied-p))
(love-is)
(love-is :a "me")
(love-is :a "me" :b "now" :c "mine")
Keywords can also use -supplied-p to inform
whether a parameter was supplied or is using
the default.

(function chosen-function)
#'chosen-function
Allows you to get a function object
The #' is the short form of function

(funcall #'chosen-function)
(chosen-function)
Two ways to call a function

(apply #'chosen-function some-list)
Apply is like funcall except it expects it's
input to be a list

(funcall #'+ (values 4 8) (values 3 9))
Funcall calls a function, but can only see
the primary values passed.

(multiple-value-call #'+ (values 4 8) (values 3 9))
Like funcall, but can see all the values passed to it.

(multiple-value-bind (x y z) (values 15 15 15)
  (+ x y z))
Accepts multiple return values.

(multiple-value-list (values 2 4 6 8))
Collects into a list

(values-list (multiple-value-list (values 2 4 6 8)))

(defparameter *taco* nil)
(defparameter *julios* nil)
(setf (values *taco* *julios*) (floor (/ 85 53)))
*taco*
*julios*
Using setf on values.

(list 4 5 6)
Create a list (4 5 6)

(list :x 4 :y 5 :z 6)
Create a plist [property list] (:X 4 :Y 5 :Z 6)

(getf (list :x 4 :y 5 :z 6) :y)
Get value by keyword symbol in a plist

(remove-if-not #'oddp '(1 2 3 4 5 6 7 8 9))
Create a new list with all non odd numbers
removed
#' = forces lisp to look up a function name
rather than a variable name
Could also be writte as:
(remove-if-not #'(lambda (x) (= 1 (mod x 2))) '(1 2 3 4 5 6 7 8 8 9))


(defparameter *bye-bye* (list 0 1 2 0 1 2 0 1))
*bye-bye*
(setf *bye-bye* (delete 2 *bye-bye*))
*bye-bye*
Delete is like remove except it destroys. Must
be careful when using delete as not to alter
shared structure. Normally use remove.

(defparameter *god-of-chaos* (list 0 1 2 3 4 5))
(sort *god-of-chaos* #'>)
*god-of-chaos*
Sort is also destructive. In the end *god-of-chaos*
may not be what you expected. You may want to make
a copy before sorting if original value is still
needed.


(defun models (x y z) (list x y z))
(models "hand" "foot" "runway")
Define function with three properties

(defun models (&key x y z) (list x y z))
(models :x "hand" :y "foot" :z "runway")
(models :z "runaway" :y "foot" :x "hand")
(models :x "hand" :z "runway")
(models)
Define function with optional keyword properties and
call them, ignored keywords default to nil
& = optional

(defun models (&key x (y "wrist") (z "lingerie" z-p)) (list x y z z-p)
(models :x "hand" :y "foot" :z "runway")
(models :z "runway" :y "foot" :x "hand")
(models :x "hand" :z "runway")
(models)
Define function with optional keyword and
set default property when not called, also
c-p to check if function was called with
that property/argument

(cons 1 (cons 2 (cons 3 nil)))
Lists in lisp are made out of cons cells, terminated by a nil

(cons 8 (cons 6 4))
If the list is not terminated by a nil, it is considered a dotted-list
[8 6 . 4]

(cons 5 (cons 4 (cons 2 3)))

(defparamater *a-global-var* 10)
defines global variable (that is overwritable)
Dynamic variables are global [special]
Referenced from anywhere, anytime
It has to be given a value. [Can not be left unbound]


(defparamater *a-global-var* 10
              "Global with document string")
Document strings can be added to dynamic variables [global]

*are called earmuffs* they are optional strictly speaking

(defvar *fi* 4)
Defines a global variable (that is not overwritable)
Although it can be changed with setf.
It will not give error if you try to change value,
it will just ignore it: (defvar *fi* 5) is still = 4
Defvar can also create unbound variables.
Variables with no initial value.
(defvar *empty-now*)

(defvar *fu*)
Defines *fu*, but does not set it.
(defvar *fu* 3)
In this case it would set, but now it can not be overwritten.
Keep in mind it can be changed with setf

(defvar *whatya-doin* "studying")
(defun come-over () (format t "I'm busy: ~a~%" *whatya-doin*))
(come-over)
(let ((*whatya-doin* "partying")) (come-over))
(come-over)
(defun excuses ()
  (come-over)
  (let ((*whatya-doin* "partying")) (come-over))
  (come-over))
(excuses)
Example of using global/dynamic variables and changing
values whithin a binding/scope and the value being
the original once out of scope.

(defun decide ()
  (format t "After deciding~14t: ~a~%" *whatya-doin*)
  (setf *whatya-doin* "not sure")
  (format t "Before deciding~14t: ~a~%" *whatya-doin*))
(decide)
(excuses)


defconstant
???

(setq cool "me")
Set symbol/variable 'cool' to "me"
Setq is an operator
Setq creates a special/dynamic variable

(setf good-num (+ 13 10))
Set symbol/variable 'good-num' to '23' 
Setf is a macro
Setf and setq act the same when setting variable values.
Setf has other functions also, that setq does not
Setf uses setq when setting variables.

(setf fname "joe" lname "mammy")
Setf can set more than one variable at a time.


(setf my-fav-num (setf your-fav-num (random 100)))
Set two variables at the same time to the
same value.

(setf homo "everyone")
Set a variable

(setf (aref homo 2) "you")
Setf for an array
Aref access elements of an array

(setf (gethash 'key homo) "yodaddy")
Setf hastable

(setf (homo a) 10)
Setf slot/field in object

(defparameter *head* (make-hash-table))
(gethash 'dope *head*)
(setf (gethash 'dope *head*) 'crack)
(gethash 'dope *head*)

(defparameter *classmates* (make-hash-table))
(setf (gethash 'smart *classmates*) 'susie)
(defun student-present (key hash-table)
  (multiple-value-bind (value present) (gethash key hash-table)
    (if present
      (format nil "Student ~a is here and alert." value)
      (format nil "Student ~a is skipping." value))))
(setf (gethash 'retard *classmates*) nil)
(student-present 'smart *classmates*)
(student-present 'retard *classmates*)
(student-present 'genius *classmates*)
Use of multiple return value, to allow you to see if
a value actually exists and is set to nil, or if it
does not exist. In this case skipping means, it does
not exist.

(maphash #'(lambda (k v)
             (format t "~a => ~a~%" k v))
         *classmates*)
Maphash like map/mapcar iterates over a hash. This
example prints out the key value pairs in a hash.

(loop for k being the hash-keys in *boys-rating* using (hash-value v)
      do (format t "~a => ~a~%" k v))
Print out key value pairs with a loop, instead of maphash.

(loop for die-side upto 20 collect die-side)
(loop for die-side from 0 downto -20 collect die-side)
Print out 0-20

(do ((list nil) (tail nil) (die-side 0 (1+ die-side)))
  ((> die-side 20) list)
  (let ((new (cons die-side nil)))
    (if (null list)
      (setf list new)
      (setf (cdr tail) new))
    (setf tail new)))
This is equivalent to the above loop.


(loop for location in (list "Downtown" "5th Ward" "Galleria")
      collect location)
Loop through a list

(loop for every-other in (list 1 2 3 4 5 6 7 8 9) by #'cddr collect every-other)
Using 'by' you can call upon a function to act on the loop.

(loop for cons-cell on (list "me" "myself" "I") collect cons-cell)
On loops by cons cell.

(loop for every-other-cons-cell
      on (list "me" "myself" "I")
      by #'cddr
      collect every-other-cons-cell)
Use by with on.

(loop for vector-elements across "rawr" collect vector-elements)
Use across for vectors.

(loop repeat 10
      for x = 5 then y
      for y = 10 then (+ x y)
      collect y)
Repeat a loop a certain number of times.

(loop repeat 10
      for y = 10 then (+ x y)
      for x = 5 then y
      collect y)
Repeat a loop a certain number of times.

(loop repeat 10
      for x = 5 then y
      and y = 15 then (+ x y)
      collect y)
'And' can replace nested fors.

(loop for (x y z) in '((10 10 10) (20 30 40) (15 30 45))
      do (format t "x:~a y:~a z:~a~%" x y z))
Destructuring with a loop.

(loop for cons on (list 5 6 7 8 9)
      do (format t "~a" (car cons))
      when (cdr cons) do (format t ", "))
Comma seperate a list with a loop.

(loop for (item . rest) on (list 5 6 7 8 9)
      do (format t "~a" item)
      when rest do (format t ", "))
Comma seperate a list with a dotted parameter.


(loop for num upto 5 append (list num num num))
Append to a list.

(loop for num upto 5 nconc (list num num num))
Nconc is a destructive append.

(loop for num from 5 to 12 do (print num))
Looping with do.

(block secret
       (loop for message from 0 return "not telling")
       (print "Are you telling the secret?")
       "The secret is loose!")
Make it till the end of the loop.

(block secret
       (loop for message from 0 do (return-from secret "not telling"))
       (print "Are you telling the secret?")
       "The secret is loose!")
Returns not telling, and exits the loop.

(loop for even-num from 1 to 20 do
      (when (evenp even-num) (print even-num)))
Print only even numbers with a loop.

(loop for even-num from 1 to 20 when (evenp even-num) sum even-num)
Sum even numbers from 1 to 20

(loop named get-em for list in '((1 21 33) (43 5 6)) do
      (loop for item in list do
            (if (evenp item)
              (return-from get-em item))))
Name a loop and return from it.
The name must be the first clause.

Loop Kewords:
collecting summing counting, do, finally

Counting words:
for, as

from, downfrom, upfrom

equals-then
in, on

Setting local variables:
with

Accumulation words:
collect, append, nconc, count, sum, maximize, minimize

Append and nconc work on lists.

Return words:
return, return-from

Conditional words:
if, when

Termination words:
while, until, always, never, thereis
loop-finish

While and until, will execute the epilogue of a loop.
While terminates the first time the test is false.
Until stops the first time test is true.

Loop-finish runs the epilogue of a loop.

Always, never, thereis terminate the loop immediately,
never running into other loops or the epilogue.

(if (loop for num in '(2 4 6 8) always (evenp num))
  (print "All numbers are even."))
Check to see if all numbers are even.

(if (loop for num in '(1 3 5 7 9) never (evenp num))
  (print "You got all odds!"))
Check to see if all numbers are odd, using never.

(loop for character across "xyz789" thereis (digit-char-p character))
Thereis exits upon finding it's match [a digit].

(loop for character across "xyzbbc" thereis (digit-char-p character))
Thereis returns nil by default, if not finding a match.

(defparameter *random-num* (loop repeat 200 collect (random 20000)))
(loop for number in *random-num*
      counting (evenp number) into even-nums
      counting (oddp number) into odd-nums
      summing number into total-summed
      maximizing number into max-num
      minimizing number into min-num
      finally (return (list min-num max-num total-summed even-nums odd-nums)))
While looping:
Counting collect how many.
Summing sums
Maximizing - gets highest number
Minimizing - collects lowest number


(defparameter *boys-rating* (make-hash-table))
(setf (gethash 'dustin *boys-rating*) 5)
(setf (gethash 'george *boys-rating*) 3)
(setf (gethash 'sam-the-man *boys-rating*) 6)
(setf (gethash 'bilian *boys-rating*) 8)
(setf (gethash 'vlado *boys-rating*) 9)
(maphash #'(lambda (k v) (when (< v 6) (remhash k *boys-rating*))) *boys-rating*)
Remove pairs with rating less than 6

+**
clrhash - completely clears a hash table of all
             key/value pairs
+**


(setf quantity 0)
(setf quantity (+ quantity 1))
(incf quantity)
(setf quantity (- quantity 1))
(decf quantity)
(setf quantity (+ quantity 5))
(incf quantity 5)
Changing a value, with +/- and incrementing
and decrementing.
Decf and incf are modify macros. [Macros built
on top of setf, that modify values based by
those values]

(setf girl-name "george")
(setf boy-name "allison")
(rotatef girl-name boy-name)
Rotatef rotates/switches the values.
The longer version would be this:
(let ((temp-name girl-name)) (setf girl-name boy-name boy-name temp-name) nil)

(setf name1 "me" name2 "myself" name3 "I")
name1
name2
name3
(shiftf name1 name2 name3)
name1
name2
name3
(shiftf name1 name2 name3)
name1
name2
name3
Shiftf shifts the values to the left.
In the end all the name1-3 will be: I
To get the end result one could:
(let ((temp-name name1)) (setf name1 name2 name2 name3) temp-name)

(let (var declaration)
  ...local area that can use lets above...)
Define local variable
Static variables are local [lexical]
Can only be referenced within construct [scope].

(let ((x 6))
  x)
Lexical scope with let.

(let ((z 90))
  (+ 45 z))


(let ((polygirl "Oh! You brought me a play toy!")
      (monogirl "WTF! I'll kill you!")
      (asian-hooker "Look what I got you for your birthday... "))
  (print "A polygirl responds: ")
  (princ polygirl)
  (print "A monogirl responds: ")
  (princ monogirl))
Example of let creating local variables

(defun boyfriend (him)
  (format t "Steady Boyfriend: ~a~%" him)
  (let ((him "Vlado"))
    (format t "Last night's boyfriend: ~a~%" him)
    (let ((him "Bilian"))
      (format t "Tonight's boyfriend: ~a~%" him))
    (format t "Last night's boyfriend: ~a~%" him))
  (format t "Steady Boyfriend: ~a~%" him))
(boyfriend "Mekel")
Let changing the boyfriend variable, inside the function.
Call with (boyfriend "chosen-name")
Binding forms, introduce new variables that are only usable
within a construct, in this case a function.

(let ((me "myself and I")) (format t "~a" me))
((lambda (me) (format t "~a" me)) "myself and I")
This let is similar to the anonymous function
below it.

(defun fun-name (args))
Defines global functions

(defun square-it (x)
  (* x x))
(square-it 8)
Define a function to square numbers, then use it on 8


(defun lego-stud-count (length width)
             (* length width))
(lego-stud-count 2 5)
Define function to find how many studs are
on a lego piece.

(defun lego-stud-count (len wid &optional (glued-on 0))
  (* (+ len glued-on) (+ wid glued-on)))
(lego-stud-count 2 5)
(lego-stud-count 2 5 1)
Define function with an optional argument

(defun lego-stud-count (len wid &key (glued-on-len 0) (glued-on-wid 0))
  (* (+ len glued-on-len) (+ wid glued-on-wid 0)))
(lego-stud-count 2 5 :glued-on-len 1)
(lego-stud-count 2 5 :glued-on-wid 1)
(lego-stud-count 2 5 :glued-on-len 2 :glued-on-wid 3)
Define function with key value optional arguements

(defun rect-2d-or-3d (len wid &optional (hgt 1))
  (* len wid hgt))
This has an optional argument. Given two values it
finds the area of a 2d rectangle. Given three it finds
the volume of a 3d rectangle. &optional (hgt 1) lets
height be optional, with a default of 1, if nothing
is entered.

(defun nookies (wife &key (girlfriend 0) (concubine 0) (fling 0))
  (princ "I am stuck with ")
  (princ (+ wife girlfriend concubine fling))
  (princ " nookies!"))
(nookies 1 :fling 5 :girlfriend 2 :concubine 1)
Use keywords for arguments with default values, must have : before name
when keywords called.

(defun mult-len-wid (len wid &rest listed)
  (print "The list of &rest are")
  (print listed)
  (* len wid))
(mult-len-wid 20 30 'my 'mammy 'and 'me)
Rest and the &rest of arguments to al list
Will return nil, if no rest values are supplied


(defvar *first-partner* "Denver")
(defvar *second-partner* "Detroit")
(defun debbie-does (*first-partner*)
  (let ((*second-partner* "Dorah"))
    (print "Debbie does")
    (princ *first-partner*)
    (print "Debbie does")
    (princ *second-partner*)
    (print "Debbie devours")
    (debbie-devours (concatenate 'string *first-partner* " and " *second-partner*))))
(defun debbie-devours (debbie-devours-args)
  (princ debbie-devours-args)
  (print "Debbie devours")
  (princ *first-partner*)
  (print "Debbie devours")
  (princ *second-partner*))
(debbie-does "Deutschland")
(debbie-devours "Eat it Debbie!")
Define globals with defvar so 'let' can access them from outside it's
scope/construct/reach whatever yous want to call it. This also has a
function calling a function. [debbie-does calls debbie-devours]
Also notice debbie-does accepts an argument that replaces the global
variable '*first-partner*' : (debbie-does "Sarah"). The let in
debbie-does replaces the globalvar '*second-partner*' whose value
originally was "Detroit" with "Dorah".

(flet ((func_name (args)
          ...func body...))
  ...area function is usable...)
Defines local function

(labels ((a (n)
            (+ n 2))
         (b (n)
            (+ (a n) 4)))
  (b 6))
Enables one local function to call another and to also call itself
Allows you to define functions locally

whitespace is ignored

-------------
(defparameter *amansthoughts* (loop for i below 100000 collect 'sex))

(defun lst-length (lst)
  (labels ((f (lst accum)
              (if lst
                (f (cdr lst) (1+ accum))
                accum)))
    (f lst 0)))

(lst-length *amansthoughts*)

;; Example of tail call function, and then using it.
;; f calls itself recursively, and can forget and
;; not put anything on the stack.
;; Notice there is also variable shadowing here:
;; lst, within f, and lst within lst-length
;; *** If using clisp, tail call functions,
;; need to be compiled, for optimization reasons

;; lst-length could also be written with the reduce
;; function, to be more functional in style:
(defun lst-length (lst)                                                    
  (reduce (lambda (x i)                                                    
            (1+ x))                                                        
          lst                                                              
          :initial-value 0))
-------------

(ash)
arithmetic shift function (halves the result and shortens the result) (binary shift)

(ash 11 1)
22
Shift bits left

(ash 11 -1)
5
Shift bits right

(princ "yum yum")
Print out a string

(cons 'me 'you)
Links to pieces of data. In this case two symbols, resulting in the cons cell:
(ME . YOU)

(cons 'me '(you them))
Adds a new item to the beginning of a list

(cons 'me (cons 'you (cons 'them ())))
Same as the above, just a longer way to write it

(defparameter *con-man* (cons 2 4))
(setf (car *con-man*) 22)
(setf (cdr *con-man*) 44)
*cons*
Using setf with the car/cdr of cons cells

(cons 3 nil)
(cons 3 (cons 4 nil))
(cons 4 (cons 5 (cons 6 nil)))

(car '(me myself I))
Retrieves first value of a cell

(cdr '(me myself I))
Retrieves the remainder of a list (skips the first value)

(cadr '(mouse dog cat shoe))
car the cdr. Retrieves only the second item

(cadr '(when (> y 20) (print y)))

(car (cdr '(mouse dog cat shoe)))
Same as above

cdar

cddr
(cddr '(when (> y 20) (print y)))

caddr

cadadr

(defparameter *dissect-me* (list '(0 1 2) '(3 4 5) '(6 7 8)))
*dissect-me*
(car (car *dissect-me*))
(caar *dissect-me*)
(car (cdr *dissect-me*))
(cadr *dissect-me*)
(car (cdr (car (cdr *dissect-me*))))
(cadadr *dissect-me*)


These are buit in up to four levels deep.
Count the a's and d's and it will tell you
how many car's and cdr's are involved.
Some must have lists inside of lists
to work.

(list 'taco 'mango 'pizza)
Creates a list

(defparameter *modme-1* (list 4 5))
(defparameter *modme-2* (list 6 7))
(defparameter *modme-3* (append *modme-1* *modme-2*))
*modme-3*
*modme-2*
(setf (second *modme-2*) 9)
*modme-2*
*modme-3*
Append shares the structure of the second item by using it
as the cdr of the first. Changing *modme-2* alters *modme-3*

'(taco mago pizza)
Same as above, creates a list

'(her (oh yes) that one)
Nested list

(if '()
    'am-i-true?
    'or-am-i-false?)
An empty list is false

(if t "oh yeah!" "or no..")
good

(if nil "nice!" "uh oh")
oops

(if "I command you" "you better do it" "make me")
Non-nil means true!

() '() 'nil nil
Four ways to represent an empty list or false

(if (= (+ 2 2) 4)
    'oh-yeah
    'no-way)

(if (evenp 6)
    'is-even
    'is-odd)

(if (> 7 9) "Of course" "Nada chance")
(if (> 9 7) "Of course" "Nada chance")
Simple if then else. One returns then,
other the else.

(if (> 7 9) "Oh yeah")
Returns NIL as there is now else.

(setf seen-hottie "blondie from other tribe")
(defun caveman-horny-p (x)
  (print "ugh ugh"))
(defun club-back-of-head (x)
  (print "smack"))
(defun enjoy-the-night-with (x)
  (print "huh uh huh uh huh uuuuu..."))
(if (caveman-horny-p seen-hottie)
  (progn
    (club-back-of-head seen-hottie)
    (enjoy-the-night-with seen-hottie)))
If statement, caveman style.
The progn lets club and enjoy, both happen. Else
the enjoy would have been an else statement and
not part of the then. A "when" would probably
be a better way to right it.
This runs because non-nil is considered 't'.
Progn lets more than one statement be executed
returning the last one.

(when (caveman-horny-p seen-hottie)
  (club-back-of-head seen-hottie)
  (enjoy-the-night-with seen-hottie))
Using when, instead of if with progn.
When lets several things happen.
Unless is the opposite of when and would
let multiple elses to be evaluated.

(defmacro when2 (condition &rest body)
  `(if, condition (progn ,@body)))
If when did not exist, you could write it
like so.

(when "sick of life" "jump!")
(when t "see ya in the afterlife!")
(when nil "just-chill")
(unless t "not happening")
(unless nil "now i'll chill")

(when t
  (print "Now in a momment...")
  (print "I'm going to ask you to open your eyes")
  (print "That's right"))
Executes several statements

(defmacro unless2 (codition &rest body)
  `(if (not, condition) (progn ,@body)))
Example of how unless could be created
if it did not exist already.

(reverse "test")
(reverse '("test" "dog" "cat"))
Returns a list in reverse

(defmacro the-backwards-man (expr) (reverse expr))
(the-backwards-man ("I'm the backwards man, the backwards man. I can walk backwards fast as you can." t format))
Define macro backwards, that can reverse a lisp expression so it is in the correct order to be evaluated, as it should be (format t "blah blah")format .

(princ (reverse "!nac I ...sdrawkcab epyt nac I nam sdrawkcaB"))
Print string backwards

(progn (princ (reverse"مالس"))
       (terpri)
       (terpri)
       (princ "hello"))
If your terminal does not support bidirectional support, you could
reverse arabic/persian script.

(format t "Holas, I am Taizya!")
Three destinations to choose from:
t = print to terminal/console [returns nil] 
    t is shorthand for *standard-output*
nil = returns as a string [prints to console]
stream = output to stream

(format t "~{~a~^, ~}" '("honey" "syrup" "molasses"))
Return values from a list, comma delimited.
~{..~} = expects a list, and loops over it

(format t "~%Holas, I am ~a" 'Taizya)
Prints to console, returns nil
~% prints a newline

(format nil "Holas, I am ~a" 'Taizya)
(format nil "You drank ~a martinis!" 11)
(format nil "~a would you like for dinner" "Who")
(format nil "Uhm.. ~a are horrible pets!" '("cats" "dogs" "birds"))
Returns as a string [with nil] 
Removes the side effect of prining NIL after evaluation
~a argument place holder replaced as string,
aesthetic, human readable, strings without quotes
keywords without the leading :
~a = Human readable

(format nil "Formatted value is: ~a" 10)
(format nil "Formatted value is: ~a" "ten")
(format nil "Formatted value is: ~a" (list 7 8 9))

(format t "This sentence can be continued on ~
           this line down here, thanks to ~~")
Use ~ by itself to break a line while coding and ignore
the extra whitespace when being evaluated/returned.
To print a ~ in the format body use ~~

(format t "Hand job $~$! BJ $~$! Nookie $~$! Balloon knot $~$"
                         10.25 20.5 30.75 40)

(format t "~a:~20t~a" :mykeyword "Come on in"
t = tabular
~20t = fill spaces to start on 20th column

(format t "~$" pi)
~$ = two decimal places [by default]

(format t "~4$" pi)
Prints out 4 decimal places.
Some directives take prefix parameters, like
this 4.

(format t "~v$" 10 pi)
Print out pi to the 10 decimal place.
v = place the prefix after the directive. 
In this case v will be replaced with 10.

(format t "~,11f" pi)
Print out pi to 11 decimal places. Using
the float directive this time.

(format t "~d" 999999999)
(format t "~d" -999999999)
(format t "~@d" 999999999)
The '@' puts a '+' in front of positive
numbers

(format t "~:d" 999999999)
(format t "~:@d" 999999999)
: = add commas in the proper places.

(format nil "~15d" 500000)
Pad with spaces.

(format nil "~15,'0d" 500000)
Pad with 0's.

(format nil "~4,'0d-~2,'0d-~2,'0d" 2012 23 12)
Date formatting

(format nil "~:d" 500000000)

(format nil "~,,'.,4:d" 500000000)
Seperate in groups of 4 by '.'



(format t "~#$" pi)
(format t "~#$" pi pi)
(format t "~#$" 5 pi)
(format t "~#$" 3.14 pi)
Playing around, not sure how to use # correctly
but this gives an idea of what it is doing.

(format t "Error: Non acceptable character: ~:c" #\space)
(format t "~@c~%" #\x)
(format nil "~:@c" (code-char 65))
(format nil "~:@c" (code-char 13))
(format nil "~:@c" (code-char 32))
(format nil "~:@c" (code-char 127))

(format nil "~f" pi)
(format nil "~,6f" pi)
(format nil "~e" pi)
(format nil "~,6e" pi)
(format nil "~$" pi)
(format nil "~2,6$" pi)

(format nil "booger~p" 1)
(format nil "booger~p" 2)
(format nil "booger~p" 0)
(format nil "~r booger~:p" 1)
(format nil "~r booger~:p" 2)
(format nil "~r booger~:p" 0)
(format nil "~r boog~:@p" 1)
(format nil "~r boog~:@p" 2)
(format nil "~r boog~:@p" 0)
Plural format

(format nil "~(~a~)" "kAte Mix COOKIES")
(format nil "~@(~a~)" "kAte Mix COOKIES")
(format nil "~:(~a~)" "kAte Mix COOKIES")
(format nil "~:@(~a~)" "kAte Mix COOKIES")
Formatting with capitalization.

(format nil "~[영~;일~;이~;삼~;사~]" 4)
(format nil "~[영~;일~;이~;삼~;사~:;너무많이~]" 5)
Conditional formatting:
~:; = default result [must be last]

(defparameter *list-em*
       "~#[NADA~;~a~;~a and ~a~:;~a, ~a~]~#[~; and ~a~:;, ~a, bunches-more~].")
(format nil *list-em*)
(format nil *list-em* 'kerry)
(format nil *list-em* 'kerry 'kat)
(format nil *list-em* 'kerry 'kat 'karen)
(format nil *list-em* 'kerry 'kat 'karen 'katia)

(format t "~:[Loser~;Winner~]" nil)
(format t "~:[Loser~;Winner~]" "non-nil")

(format nil "~@[x = ~a ~]~@[y = ~a ~]~@[z = ~a~]" 15 30 45)
(format nil "~@[x = ~a ~]~@[y = ~a ~]~@[z = ~a~]" 15 nil 45)
(format nil "~@[x = ~a ~]~@[y = ~a ~]~@[z = ~a~]" nil nil nil)

(format nil "~{~a, ~}" (list "hamster" "kitty" "puppy"))
(format nil "~{~a~^, ~}" (list "hamster" "kitty" "puppy"))
(format nil "~@{~a~^, ~}" "puppy" "kitty" "hamster")
(format nil "~{~a~#[~;, and ~:;, ~]~}" (list "kitty" "puppy" "hamster"))
(format nil "~{~a~#[~;, and ~:;, ~]~}" (list "rawr" "meao"))
~^ = Remove the last comma


(defparameter *or-listing*
  "~{~#[neither~;~a~;~a or ~a~:;~@{~a~#[~;, or ~:;, ~]~}~]~:}")
(format nil *or-listing* '())
(format nil *or-listing* '("me" "myself"))
(format nil *or-listing* '("me" "myself" "I"))
Put an or in more than one item.


(format nil "~r ~:*(~d)" 100)
(format nil "I have ~r wi~:*~[ves~;fe~:;ves~]." 1)
(format nil "I have ~r wi~:*~[ves~;fe~:;ves~]." 2)
~* = jump
~:* = jump backwards

(format nil "~{~s~*~^ ~}" '(:x .5 :y 10))
Print only keys of a plist with ~*



;; Format control arguments/characters [directives]
~$ = formats money, decimal two places [default]
~f = float
~d = decimal integer
~% = newline
~& = freshline
~ = ignore whitespace till next non-whitespace character
~a = print lisp object as string w/o quotes [human readable, aesthetic]
~s = print lisp object without quotes, it also 
     attempts to make output capable of being 'read' back in.
~c = character
~:c = print out nonprinting characters
~@c = print lisp literal character syntax
~:@c = ascii code
v = place the prefix after the directive. 
~| = page seperator/break, form feed [^L] for printers and [emacs ^c^l] 
# = ???? not sure yet, got some funky results with it.

~p = pluralizes words greater than 1

~r = [~radix,mincol,padchar,commachar,comma-intervalR]
     radix=base [default is base 10, decimal]
     ~r = cardinal english
     ~:r = ordinal english
     ~@r = newer style [IV IX] 
     ~:@r = older style [IIII VIIII]

~b = binary
~o = octal
~x = hex

~[ ... ~[ = Conditional formatting
~{ ... ~{ = Iteration

Lisp supports bases 2-36.
There are 26 letter in english alphabet
There are 10 unique numbers. (0-9)
26+10 = 36 possible bases.
Put # before the base value, then r, then number value.
To use base 36:
#36rz
#36r10
And base 20:
#20rj
#20r10
Base 2, 8, 16 are binary, octal, hex and
can also be represented with:
#b10
#o10
#x10
The default base is 10. Which can be seen with:
*read-base*
If you are an old school mayan and the decimal
system is jacking you up, you could change to
vigesimal [base 20], by changing *read-base*.
(setf *read-base* 20)
Then you could use 0-k as your numbers normal
numbers.
Note: To get back to base 10 from base 20:
(setf *read-base* a)
As 10 = 20, in base 20. So if you said
(setf *read-base* 10) you would be resetting
it to base 20 again. A = 10 in base 20.

There are four types of floating point numbers:
short, single, double, long or s,f,d,l
Floating points are always base 10.
1.0e4 [e = normal, s,f,d,l can also be used]
Scientific notation.

#c(3 1) = #c to represent complex number
[real imaginary]
(+ #c(3 2) #c(9 5))

Rounding can be done with:
floor, ceiling, truncate.

Modding:
mod, rem
mod similar to perl/python %
rem similar to c/java %

Increment/decrement:
1+ or incf and 1- or decf
(incf n) === (setf n (1+ n)) === (setf n (+ n 1))

(format t "~10a following me" 'quit)
Control characters can take padding

(format t "Use ~~s to print a ~s over there" "string")
(format t "Use ~~a to print ~a no quotes [no delimiter]" "string")
(format t "Skipping 12 spaces~12@a!" "rawr!")
(format t "skipping 12 spaces on left ~12@a" "rawr!")
(format t "Padding 6 extra ~,,6a right there" "spaces")
(format t "Print 12 spaces in groups of 4 ~12,4a there" "spaces")
(format t "Pad five ~,,5,'!a" "bars")
(format t "Pad six ~,,6,'!@a left" "bars")
(format t "Hexadecimal 47806 is a ~x!" 47806)
(format t "Binary 47806 is ~b" 47806)
(format t "Decimal 47806 is ~d" 47806)
(format t "Comma'd ~:d up!" 47606)
(format t "Space ~12d it again..." 47806)
(format t "Are you sleepy ~12,'zd ?" 47806)
(format t "48706.48706 is ~8f" 47806.47806)
(format t "48706.48706 is ~,8f" 47806.47806)
(format t "~,,2f percent lisp" .47806)
(format t "Who's your char~c boiy" #\?)
(format t "Next page please ~3| Hmm.. Don't like me?")
(format t "How do you say ~r, in english?" 127)
(format t "What place did you rank? ~:r" 127)
(format t "Them young romans counted like: ~@r" 129)
(format t "Them ancient romans liked counting like: ~:@r" 129)


(defun had-sex (with-partner with-someone-else
                             &optional (tell-partner nil tell-partner-p))
  (let ((total-times (+ with-partner with-someone-else)))
    (when tell-partner-p
      (format t "~%You Choose to~
              ~:[ **to keep it a SECRET** ~; **rat yourself out!**~]"
                       tell-partner)
              (if tell-partner
                (format t "~%You cheated on me! We are DONE!!~
                        ~%At least you got to bang your partner... ~:d times, before the beak up!."
                        with-partner) 
                (format t "~%You sly little devil.. You cheated ~:d times without getting caught!"
                        with-someone-else)))
              (format t "~%You did the nasty ~:d times in total!"
                      total-times)))
(had-sex 4 8)
(had-sex 4 8 1)
(had-sex 4 8 nil)
Tell-partner-p with :[ conditional between this ~; and this]
depending on what is passed in arguments. Using nil lets you
not tell on yourself. ~:d is decimal when using format t.

progn
Stuff extra commands in a single expression

(progn (princ "holas")
   (terpri)
   (princ "hello"))

'Terpri' starts a new line

(progn (princ "안녕하세요")
   (fresh-line)
   (princ "hello"))
'fresh-line' starts a newline, if cursor not at front of first line

(progn (princ "안녕하세요")
   (fresh-line)
   (fresh-line)
   (princ "hello"))
Two 'fresh-line's only make one new line


(progn (princ "سلام")
       (terpri)
       (terpri)
       (princ "hello"))
Prints two newlines

(progn (format t "~~% is equivalent to terpri ~%")
       (format t "~%yep, down here...."))
~% is equal to terpri


(progn (format t "~~& is equivalent to fresh-line ~&")
       (format t "~&does not make two lines"))
~& only creates one new line

(format t "Jump five lines ~5% about here")
Add extra lines

(defun random-programer ()
  (nth (random 7) '("asm" "ruby" "c" "python" "lisp" "tcl" "haskel")))
(random-programer)
(loop repeat 12
      do (format t "~6t~a ~18t~a ~30t~a~%"
                 (random-programer)
                 (random-programer)
                 (random-programer)))
(loop repeat 10
      do (format t "~30<~a~;~a~;~a~>~%"
                 (random-programer)
                 (random-programer)
                 (random-programer)))
(loop repeat 16 do (format t "~30:@<~a~>~%" (random-programer)))
(loop repeat 12
      do (format t "~30:@<~a~;~a~;~a~>~%"
                 (random-programer)
                 (random-programer)
                 (random-programer)))
(loop repeat 15
      do (format t "~10:@<~a~>~10:@<~a~>~10:@<~a~>~%"
                 (random-programer)
                 (random-programer)
                 (random-programer)))
Print out in tabular format
Second loop: spaces out evenly per line, [not column]
Third loop: print one column centered middle
Fourth loop: almost aligned
Fifth loop: all columns centered with each other evenly spaced
~t = tabular

(setq do-it 0)
(loop
  (setq do-it (+ do-it +1))
  (print do-it)
  (when (> do-it 10)
    (return do-it)))


(defun random-bsds ()
  (nth (random 38) '("open-bsd" "net-bsd" "freebsd" "dragonflybsd"
                     "pc-bsd" "archbsd" "junos" "386bsd" "bsd/os"
                     "sunos-4.1.4" "ultrix"  "tru64-unix" "os-x"
                     "ios" "darwin" "ghostbsd" "desktopbsd"
                     "closedbsd" "freesbie" "picobsd" "nanobsd"
                     "anonym.os" "miros-bsd" "microbsd" "ekkobsd"
                     "4.4bsd" "dynix" "next" "nextstep" "dec"
                     "gentoobsd" "kfreebsd" "pfsense" "paxym"
                     "maheshabsd" "karmabsd" "jibbed" "midnightbsd")))
(defparameter *bsds* (loop repeat 38 collect (random-bsds)))
format t "~{~a has bsd influence! ~}" *bsds*)
Print out OSes with BSD influence


(format t "|~{~<|~%|~,33:;~2d ~>~}|"
        (loop for x below 204 collect x))
Create chart from 0 to 203


when
Enclosed expressions are evaluated when true

unless
Enclosed expressions are evaluated when false

cond
Can handle more than one branch

(cond (1 (print "blah"))
      (2 (print "blah blah"))
      (t (print "nahnhanahanah")))
(cond (nil (print "blah"))
      (2 (print "blah blah"))
      (t (print "nahnhanahanah")))
(cond (nil (print "blah"))
      (nil (print "blah blah"))
      (t (print "nahnhanahanah")))
Cond can be more convienient than trying
to nest mulitple ifs, and branching with them.

(setq mood "happy")
(cond
  ((equal "happy" mood) "I feel great")
  ((equal "sad" mood) "This planet sucks")
  ((equal "whatever" mood) "meh"))

case
Can be used to branch on symbol values
***cannot be used to branch on strings***
Since it is using: eq for it's comparisons
Case will return nil, if it has no matches.

ecase
Error case / exhaustive case
Signals an error the key value does not match
any listed keys.

(setq her 'doable)
(case her
  (ugly "if i was drunk")
  (doable "i'd do it")
  ((nasty dirty) "if she showered")
  (otherwise "of course!"))

(and (evenp 6) (evenp 8) (evenp 4))
Using and conditional to check if three values are even

(or (evenp 2) (evenp 3) (evenp 5))
Using or to see if at least one value is even

(not nil)
(not (= 9 9))
(and (= 7 8) (= 8 8))
(or (= 7 8) (= 8 8))
Not is a function, "and" and "or" are macros.
Not inverts a boolean value.
And all values need to be true.
Or any/just one value needs to be true.

(if (member 4 '(2 3 1 4 5))
    'four-is-present
    'four-is-not-here)
Check to see if value is present in a list

find-if


Use eq to compare symbols [pronounced 'eek']
Use equal for everything else

eq
Used to compare symbols

eql
Like eq but also compares numbers and characters

equal
Used to compare everythig except symbols

equalp
Like equal, but can compare different capitalization
and integers with floats
As in (equalp 3 3.0)

=
For numbers

string-equal
For strings

char-equal
Compare characters, case insensitive

char=
Compare characters, case sensitive.

/=
T if all arguments have different values

These also exist:
<, >, <=, >=
(< 2 3 5)
(<= 5 2 3 0 1)

min
Pick out smallest number

max
Pick out highest number

zerop
Test for 0

minusp
Test for negative number

plusp
Test for positive number

not-greaterp
not-lessp

Character Comparison Functions
Numeric Analog  Case-Sensitive  Case-Insensitive
=               char=           char-equal
/=              char/=          char-not-equal
<               char<           char-lessp
>               char>           char-greaterp
<=              char<=          char-not-greaterp
>=              char>=          char-not-lessp

String Comparison Functions
=               string=           string-equal
/=              string/=          string-not-equal
<               string<           string-lessp
>               string>           string-greaterp
<=              string<=          string-not-greaterp
>=              string>=          string-not-lessp

(string= "polygamy" "monogamy" :start1 4 :end1 8 :start2 4 :end2 8)
Match a substring from two words
:end can be left off to match till end of string

(string/= "lisp" "lispalot")
Returns the index [placeholder] of the first mismatch of
the compared words


Higher Math Functions
log
exp
expt
sin
cos
tan
asin
acos
atan
sinh
cosh
tanh
asinh
acosh
atanh

alist
An association list, key/value pair

(assoc 'x '((x . 15) (y . 30) (z . 0)))
(assoc 'y '((x . 15) (y . 30) (z . 0)))
(assoc 'z '((x . 15) (y . 30) (z . 0)))
Using assoc on an alist.

(cdr (assoc 'x '((x . 15) (y . 30) (z . 0))))
Cdr on assoc can give value, rather than key

(assoc "joey" '(("shawn" . "arragant") ("joey" . "cute")) :test #'string=)
Use :test string= to find strings in alist.

(cons (cons "mikey" "funny") '(("joey" . "cute") ("shawn" . "boring")))
(acons 't 30 '((x . 0) (y . 0) (z . 0)))
Use cons to add to the beginning of a list.
Acons as well

(setf heroes (acons 'archer 'arrows '(('knight . 'sword) ('thief . 'dagger))))
Setf to actually change the value with acons.
Push can also be used

(defparameter *inventory* '(('potion . 1) ('gum . 2)))
(push (cons 'herbs '1) *inventory*)
*inventory*
Alists can be faster than a hash table, for small tables,
larger ones should use something other than alists. Alist
is probably best for small data tables.

copy-tree

copy-alist
assoc
assoc-if
assoc-if-not
rassoc
rassoc-if
rassoc-if-not
Rversions operate on cdrs, as a reverse lookup.

parilis
Used to build an alist out of two seperate lists.

(pairlis '(x y z) '(10 5 15))
Combines two lists into an alist. The pairs may
come out in the same order or in reverse.

(defparameter *opp* ())
*opp*
(setf (getf *opp* :x) 10)
*opp*
(setf (getf *opp* :x) 15)
*opp*
(remf *opp* :x)
*opp*
Add pair to a plist, change value, then delete pair

symbol-plist
setf get getf
remf
remprop


(destructuring-bind (r g b) (list 255 255 0)
    (list :r r :g g :b b))

(destructuring-bind (good bad ugly) (list "kat" "shnack" "ash")
  (list :good good :bad bad :ugly ugly))

(destructuring-bind (good bad ugly)
  (list "dog food" (list "dry cat food" "wet cat food") "goolosh"))

(destructuring-bind (boy (girl1 girl2) tranny)
  (list "mekel" (list "candace" "sarah") "ginger")
  (list :boy boy :girl1 girl1 :girl2 girl2 :tranny tranny))

(destructuring-bind (cdrom (monitor1 &optional monitor2) tower)
  (list "burner" (list "crt" "lcd") "sgi")
  (list :cdrom cdrom :monitor1 monitor1 :monitor2 monitor2 :tower tower))

 (cdrom (monitor1 &optional monitor2) tower)
         (list "burner" (list "crt") "sgi")
               (list :cdrom cdrom :monitor1 monitor1 :monitor2 monitor2 :tower tower))

(destructuring-bind (&key xaxis yaxis zaxis)
  (list :xaxis 8 :yaxis 12 :zaxis 40)
  (list :xaxis xaxis :yaxis yaxis :zaxis zaxis))

(destructuring-bind (&key x y z) (list :z 22 :y 33 :x 44)
  (list :x x :y y :z z))

(destructuring-bind (&whole whole &key x y z)
  (list :z "zz" :y "yy" :x "xx")
  (list :x x :y y :z z :whole whole))

'
There are two modes in lisp. Code mode and 'data-mode
' marks data

`
quasiquoting creates chunks of data with embedded lisp code
, the comma unquotes to flip in and out of code mode during quasiquoting

`(6 7 (+ 8 9))
`(6 7 ,(+ 8 9))
Shows how the , lets code be executed when
quasiquoted

`(and ,(list 6 7 8))
`(and ,@(list 6 7 8))
`(and ,@(list 6 7 8) 9)
Show how ,@ can splice values together

mapcar
Takes a function and applies it to every member of a list

(mapcar (lambda (x)
         (+ x 3))
 '(1 2 3 4 5 6 7 8 9))
Adds three to each number in a list

(mapcar #'(lambda (x) (* 5 x)) (list 4 5 6))
(mapcar #'+ (list 7 8 9) (list 9 8 7))

mapc
Like mapcar but does not return the transformed list

Functions that take other functions as parameters are called:
higher-order functions

#'
Shorthand for the function operator

call-aruments-limit
Shows the maximum number of allowed arguemnts to a function
[not a modern problem]


Functions that return true or nil are called predicates and
are named with a p at the end. Such as: evenp, oddp,
user-created-function-p


push/assoc
To replace a value from an alist, push new items onto the
list. assoc will only report the most recent value


print
prints a newline before a value, and a space afterwards

prin1
Same as print without the newline and space

princ
Prints for humans
Cannot be read back into lisp

#\newline
#\tab
#\space

(read)
(read *standard-input*)
User input

read-line
Takes user input as a string

|recongnizeCaseWithPipes|
Vertical pipes around symbol names will make them case sensitive

eval
Execute code. [ex: variable that contains code]
'(+ 1 2)
Will not execute but this will:
(eval '(+ 1 2))

#'
Function operator [can be used to describe a defined function]

lambda
A macro that defines and uses a function withough giving it a name
Anonymous functions.

((lambda (x) (+ 3 x)) 5)
Simple lambda function example.

(funcall #'(lambda (x) (* x x)) 9)
(funcall (lambda (x y) (+ x y)) 60 40)
((lambda (x) (* x x x)) 9)
Examples of using lambda

-------------------------------------
(defmacro my-let (variable-name values &body body-of-macro-code)
  `(let ((,variable-name ,values))
     ,@body-of-macro-code))

(my-let mul-add (+ 20 10)
        (* mul-add mul-add))

Define a macro called my-let and then use it
to to create mul-add
&body = put all remaining expressions in a nested list
        This lets my-let have multiple statements
        if needed. Like the normal let.

(my-let mul-add (+ 3 2)
        (princ "Add then multiply and print evalution:")
        (* mul-add mul-add))

(let ((mul-add (+ 20 10)))
  (* mul-add mul-add))
This is what the normal let would look like.
Notice it has more parantheses.

Lisp Macros let you create you own languages.
DSL - Domain Specific Language

Basically lisp uses macro expansion to turn
you macros into actual lisp code that it
understands, before trying to run it.
When you define a macro, you are teaching
lisp how to translate your code to lisp.

Macros are run before the program
[Macro Expansion Time]. A function
is run at runtime.

(macroexpand '(my-let mul-add (+ 5 8)
                      (* mul-add mul-add)))
Macroexpand displays the raw code that is
generated by a macro. It will return T
stating that it was a valid macro and
could expand the code. This is useful
for debugging and testing macros and
their structure. Show lower level
than macroexpand-1.

Macroexpand-1
Takes lisp expression as argument and
returns the result of doing one level
of macro expansion. This can be better
for checking out your own macros than
macroexpand, as it won't expand other
macros such as do and loop.

*** Quasiquoting is used: ` , , ,@
,@ = is needed to represent the body

(defun addem (x y)
  (my-let z (+ x y)
          (format t "Add em up and get ~a" z)
          z))
(addem 45 20)
Create a function called addem, that adds
two numbers, and uses the my-let macro.
-------------------------------------

higher-order functional programming
Passing functions as values

(substitute-if #\a #'digit-char-p "Joe M4mmy h9s 4 fine 9ss")
Substitutes any digits that are found to the letter a

(subst 1 20 '(0 20 (0 20 0) ((20 20) (0 0))))
Subst works on cons cells. Subst works on trees, while
substitute works with sequences.

functions-with-not-at-end-not
Functions with not at end in common lisp are considered
deprecated and could be taken out at any time

complement
Opposite and can be used instead of a function with not at end
(complement #'alphanumeric)

nullary functions
Small functions that have zero arguments

thunk or suspenion
nullary functions that describe a computation that are to be
ran later

(with-open-file (my-stream
                  "test-write-file.txt"
                  :direction :output
                  :if-exists :supersede)
  (princ "Whoopie! I'm in the file now?" my-stream))
An example of writing text to a file

(with-open-file (stream "read-me.txt")
  (format t "~a~%" (read-line stream)))
Read a line from a file

(with-open-file (stream "just-created.txt" :direction :output)
  (format stream "Lisp just made me!"))
Create a file.

(let ((flof (open "read-me.txt")))
  (format t "~a~%" (read-line flof))
  (close flof))
Read the first line of a file.
with-open-file is safer to use and will make sure
the file is closed, even if error early return.

(let ((flof (open "read-me-not.txt" :if-does-not-exist nil)))
  (when flof
    (format t "~a~%" (read-line flof))
    (close in)))
Display first line of a file, if it does not exist
return nil.

(let ((cat-file (open "read-me.txt" :if-does-not-exist nil)))
  (when cat-file
    (loop for line = (read-line cat-file nil)
          while line do (format t "~a~%" line))
    (close cat-file)))
Print out all lines of a file.

Need a file with s-expressions in it for next example.
Create such a file in bash called sexp-demo.txt:
echo -e '(4 5 6)\n789\n"string me up baby!" ;lisp comment\n((a b)\n (c d))' > sexp-demo.txt

(defparameter *sexpy* (open "sexp-demo.txt"))
(read *sexpy*)
(read *sexpy*)
(read *sexpy*)
(read *sexpy*)
(read *sexpy*)
(read *sexpy*)
(read *sexpy*)
(close *sexpy*)
After setting the open file to a variable, you can
return out each line by recalling read on the variable.
In this case each line is an s-expression
The comment does not get returned.
This could be used for a configuration file,
for instance.

***
read-byte
reads binary data
'(unsigned-byte 8)

read-sequence
read-char
write-char
write-string
terppi
fresh-line


pathnames
host, device, directory, name, type, version

pathname-host
pathname-device
On windows these one of these should show the
drive letter of the file. Irrelevant on *nix.

pathname-version
??

*default-pathname-defaults*
Shows current/default pathname

(pathname-directory (pathname "/home/meema/old.txt"))
Examine the directory components of a files pathname.

(pathname-name (pathname "/home/peepa/real-old.txt"))
Return the name of the file, without type/extention

(pathname-type (pathname "/usr/bin/clean-diaper.txt"))
Returns the type/extention of the file.

(pathname "/home/homo/you-be.txt")
show pathname syntax

(namestring #p"/um/whereme/be.txt")
Uses a pathname designater to return a namestring

(directory-namestring #p"/some/file/here.txt")
Combines directory components returning
directory structure

(file-namestring #p"/root/lier/not-me.txt")
Combines name and type for filename.

(pathname-name (pathname "/home/me/.hoe"))

(pathname-type (pathname "/home/me/.hoe"))
Will retrun nil on most unix implementations

(file-namestring (pathname "/test/me/now.txt"))
Includes the version if the fs supports it

(make-pathname
  :directory '(:absolute "home" "mymammy")
  :name "andme"
  :type "txt")
Creates a pathname from the given components.
This way the code can work on several file
systems.

(make-pathname :device "c" :directory
               '(:absolute "user" "bilian") :name "pesos")
This would only work on some implementations of windows,
as the drive letter can be stored in :device or :host


(make-pathname :type "html" :defaults "holas")
(make-pathname :directory '(:relative "pickles") :defaults "bite-me.txt")
(make-pathname :type "xml" :version :newest :defaults "this-file")
Safer ways to create pathnames

(make-pathname :directory '(:relative "class-notes")
               :defaults #p"/myfiles/storage/math.txt")

(merge-pathnames #p"/killer/bees/yall.txt" #p"/www/beehive/sting.html")
(merge-pathnames #p"/killer/bees/" #p"www/beehive/sting.html")
(merge-pathnames #p"/killer/" #p"/www/beehive/sting.html")
(merge-pathnames #p"killer/bees/" #p"/www/beehive/sting.html")
Merge pathnames can overide what is not there. Can also
merge relative and absolute paths.

(enough-namestring #p"/xml_pub/rsite/rawr.xml" #p"/xml/")
Get a relative path.

(merge-pathnames
  (enough-namestring #p"/home/users/julio/.vimrc" #p"/home/")
  #p"/config-bkup/")
Change root directory creating a path.

(make-pathname :name "tester" :type "rb")

(merge-pathnames #p"suzie.gif")
This will fill in the rest of the path with
whatever: *default-pathname-defaults*
is set to.

(make-pathname :directory '(:absolute "gogo") :name "dancer")
(make-pathname :directory '(:absolute "gogo" "dancer"))
Create directory paths
The second example returns with an ending: /

probe-file
rename-file
delete-file
ensure-directories-exist
file-write-date
file-author
file-length
file-position

(file-write-date "read-me.txt")
Shows seconds from 01.01.1900 gmt

(file-author "read-me.txt")
Show owner of file

(with-open-file (in "read-me.txt" :element-type '(unsigned-byte 8))
  (file-length in))
Safer to use than file-length. This returns bytes, where file-length
can chande per implementation.

Two Other ways to get file size:

(with-open-file (inside "read-me.txt")
  (loop while (read-char inside nil) count t))

(with-open-file (in "read-me.txt")
  (let ((scratch (make-string 4096)))
    (loop for read = (read-sequence scratch in)
          while (plusp read) sum read)))


(let ((s (make-string-input-stream "2.45")))
  (unwind-protect (read s)
    (close s)))
Convert string to float

Also like this:
(with-input-from-string (s "2.45")
  (read s))


(with-output-to-string (boom)
  (format boom "pshhhfffa ")
  (format boom "~s" (list 4 5 6)))
Create a new string

*features*
Displays a list of features under the current
implementation. [It is a list of symbols]

(defun which-implementation ()
  #+sbcl (print "haha! I am sbcl")
  #+clisp (print "hmm. You can call me clisp")
  #-(or sbcl clisp) (error "Figure out which lisp yourself!"))
Will run code depending on which implenattion
of lisp, the code is running under.
Some others are: allegro cmu

(directory (make-pathname :name :wild :defaults "~/"))
Get a list of files in the current user's home
directory

(defparameter *movie-set* ())
(adjoin "lights" *movie-set*)
*movie-set*
(setf *movie-set* (adjoin "lights" *movie-set*))
*movie-set*
(pushnew "camera" *movie-set* :test #'equal)
(pushnew "camera" *movie-set* :test #'equal)
*movie-set*

(subsetp '(5 6 7) '(4 5 6 7))
(subsetp '(5 6 7) '(8 9 10))
Checks to see if first sequence is a sub set of
the second. Returns: t or nil

(defvar *chosen-directory*)
(defvar *chosen-file*)
(defun import-file (file directory)
  (let ((*chosen-directory* directory)
        (*chosen-file* file))
    (print *chosen-directory*)
    (print *chosen-file*)
    (load-this)))
(defun load-this ()
  (load (merge-pathnames *chosen-directory* *chosen-file*)))
This is a long and drawn out waty to load file and can be
called like this:
(import-file "~/nixfilepath/testing/" access-me-lisp.txt")
(import-file "c:\\winfilepath\\testing\\" "access-me-lisp.txt")


:before-a-symbol
Is a keyword symbol (a constant)
Any symbol that starts with a ':'
is a keyword. Keywords evaluate to
themselves.

(loop for cons on '("gumbo" "jambalaya" "boudin")
      do (format t "~a" (car cons))
      when (cdr cons) do (format t ", "))
Print out values in a list, comma delimited.

(loop repeat 8
      (collect 2)
collect 8 2s (prints eight2s) 

(loop for n from 1 to 10
      collect n)
Count to 10


let
Can not refer to another defined variable

(let ((x 2))
  (+ x (let ((x 20))
         (+ x 2))))
Not a smart way to use let, but lisp e'll let you. 2+20+2=24
Inner binding shadows the outer, if two variables are named
the same.

let*
Can refer to another defined variable
You can just use let* unless there is a reason to use let.

(let* ((x "Taizya")
       (y x))
  (print "My ex-girlfriend is")
  (princ x)
  (print "My girlfriend is")
  (princ y))
Let* lets y = x. Let will not let you do this. As it can
not refer to another variable in the scope. Let will not
let you have girlfriend y who is your ex-girlfriend x.
Let* lets you have as many ex-girlfriends as you want
to be your girlfriend.
Also my girlfriends are local x y [they are using let]. No
other parts of the program can see them, unless I let them
be coded in here with my girlfriends, and that is not
gonna happen, at least not in this example.

(let* ((me "joe")
       (myme (concatenate 'string me "mammy")))
  (list me myme))
Let* let's myme use me.
A simpler example below.

(let* ((x 50)
       (y (+ x 30)))
  (list x y))
Let* lets y use x in it's definition. Let will not.
Although you could just use two lets, as below.

(let ((me "joe"))
  (let ((myme (concatenate 'string me "mammy")))
    (list me myme)))
Using two lets to accomplish what let* would do.

(let ((x 50))
  (let ((y (+ x 30)))
    (list x y)))
Using two lets to accomplish what let* would do.
Same as above.

(make-array 4)
Create an array of size 4

(make-array 6 :initial-element nil)
Create a single dimensional array [vector]
with 6 elements all initialized to nil.

(defparameter *z* (make-array 6 :initial-element nil :fill-pointer 0))

(vector-push 'c *z*)
Push an element onto a vector
Can be used on arrays that have a fill-pointer.

(vector-pop *z*)
Pop the last element off a vector.

(make-array 6 :fill-pointer 0 :adjustable t)
Create an adjustable vector. Which can
hold more than 6 elements.

adjust-array
Can also be used to modify arrays.

(vector-push-extend 'g *z*)
Lets you extend an adjustable vector/array and
add an element even if it is full.
...-extend is used for arrays that have a fill-pointer
and are adjustable.

(make-array 5 :fill-pointer 0 :adjustable t :element-type 'character)
Create an adjustable string vector. Strings such as "this one"
are usually fixed.

(defparameter kitten (make-array) 3))
(setf (aref kitten 1) 'crazy)
Sets the 2nd value in the kitten array to 'crazy
(aref kitten 1)
Return the 2nd value of the array kitten

(defparameter *y* (vector 4 5 6))
(length *y*)
(elt *y* 0)
(elt *y* 1)
(elt *y* 2)
(setf (elt *y* 0) 11)
*y*
Create vector *y* as (4 5 6)
Then use 'elt' to to view each element
Set the 0 index of *y* to 11
Now you can view *y* as: (11 2 3)

Simple Sequence Functions
Name         Required Arguments         Returns
count        Item and sequence          # of times item appears
find         Item and sequence          Item or nil
position     Item and sequence          Index into sequence or nil
remove       Item and sequence          Sequence with item removed
substitute   New item, item, sequence   Sequence with item replaced   

(count 'friend '(friend enemy stranger friend))
(count 4 #(2 3 4 5 6 5 4 3 2 3 2 1 0))
(find 6 #(1 2 3 4 5 6 7 6))
(find 'me '(him her you them me))
(find 100 #(1 2 3 4))
(position 14 #(12 13 14 15))
(position 'yep '(yes no hrm yep))
(remove 1 '(1 1 1 2 1 3 1 4 1))
(remove 'bad '(good bad ugly))
(substitute 0 2 #(1 2 1 2 1 2 1 2))
(substitute 'me 'team '(there is no you in team))

(count 10 '(10 2 1) :test #'equalp)
Test to see if 10 is in sequence

(count 10 #(10 2 1) :test (complement #'equalp))
Returns how many items are not 10

(count 10 #(10 2 1) :test-not #'equalp)
Returns how many items are not 10
*** This is deprecated and complement should
    be used instead. [like above]

(count 'kat '(kitty kitty bang bang kat) :test (complement #'equalp))
Returns how many items are not: kat

(count "kat" #("kat" "is" "hot") :test #'string=)
Count how many straings are: "kat"

(find 'q #((o 15) (p 16) (q 17)) :key #'first)
Find item with q in the first position 

(find 'q #((o 15) (p 16) (44 q)) :key #'second)
Find item with q in second position

(find 'z #((z 5) (w 23) (z 42) (b 69)) :key #'first :from-end t)
Find item with z in first posistion starting from
the end.

(find 'z #((z 1) (z 2) (z 3)) :key #'first :start 1)
Start from the index 1 instead of 0.

(find 'z #((z 1) (z 2) (z 3)) :key #'first :start 1 :end 3)
:end could also be added to search a subsequence.

(remove #\a "abracadabra")
Remove all 'a's

(remove #\a "abracadabra" :count 3)
Remove the first three 'a's

(remove #\a "abracadabra" :count 3 :from-end t)
Remove the last 3 'a's

(defparameter *r* #((p 0) (o 9) (n 0x)))
(defun verbose-first (c) (format t "Crack how? ~s~%" c) (first c))
(count 'n *r* :key #'verbose-first)
(count 'n *r* :key #'verbose-first :from-end t)

Standard Sequence Function Keyword Arguments
Argument     Meaning                   Default
:test        2 arguments item or       eql
             :key to element
:key         1 argument extracts
             key value from element    nil
             nil means leave as is
:start       Starting index of         0
             subsequence
:end         Ending index, nil
             states end of sequence    nil
:from-end    If true reverses order,  
             end to start

:count       Number of elements to    nil
             remove or substitute,
             nil to affect all for
             remove and substitute

(count-if #'oddp #(3 4 5 6 7))
(count-if-not #'oddp #(3 4 5 6 7))
Count odd and not odd numbers in sequence

(position-if #'digit-char-p "d0n0ut2")
Show position of the first number if
there is one

(remove-if-not #'(lambda (y) (char= (elt y 0) #\k))
            #("kat" "jack" "john" "miriam"))
Go through sequence and remove all elements
not starting with a 'k'

(count-if #'oddp #((4 h) (3 d) (2 c) (1 z)) :key #'first)
(count-if-not #'oddp #((4 h) (3 d) (1 z)) :key #'first)

(remove-if-not #'alpha-char-p #("123" "3y3z" "hi" "there")
            :key #'(lambda (y) (elt y 0)))
Remove any element that is not pure alphabet
characters

(remove-duplicates #(1 0 2 0 1 3 0 0 1 4 0))
Remove any duplicates in the sequence, leaving
just one of each

(copy-seq #(1 2 3))
Makes a new copy of the sequence, of the same
type

(reverse #(5 4 3 2 1))
Reverses the sequence by making a new one
of the same type

(concatenate 'vector #(2 4 6) '(3 5 7))
Concatenates and returns a vector

(concatenate 'list #(2 3 4) '(5 6 7))
Concatenates and returns a list

(concatenate 'string "You talking to " '(#\m #\e #\?))
Concatenate and return a string

(sort (vector "lisp" "is" "horrible") #'string<)
Sort sequence as string alphabetically
There is also: sort-stable which will not
reorder equivalent elements. Sort is destructive
so you should pass it to another function or
assign it to a variable, like so:
(setf wrong-order '(2 4 5 3 1))
(setf wrong-order (sort wrong-order #'<))

(merge 'vector #(9 7 5) #(10 8 6) #'>)
(merge 'vector #(9 7 5) #(10 8 6) #'<)
Merges the to sequences into one. If
they are in a correct sort order already
they will get sorted when combined, else
it will just merge them without them
being sorted.

(subseq "hey come here now!" 4)
Pulls out a subsequence of a sequence,
from a determined starting point

(subseq "hey come here now!" 4 17)
Pulls out a subsequence of a sequence,
from a determined starting point till
a chosen ending point.

(defparameter *m* (copy-seq "mammamia"))
(setf (subseq *m* 2 5) "rru")
Define *m* then change it with setf and
a subsequence. If the subseq and the
sequence are not the same length, the
shorter will override, ommitting the rest.
Examples below:

(setf (subseq *m* 5 8) "eeee")
The are too many 'e's so the last is
dropped off. 5-8 only allows for 3.

(setf (subseq *m* 5 8) "e")
There are not enough 'e's to fill
5-8 so only one character will be
replaced.

(search "kat" "ekatylin")
Search for the starting point of subseq
in a sequence. Similar to position, but
can find a sequence rather than just a
single character.

(mismatch "katy" "kathleen")
Returns the index [place] where the two
sequences diverge. Will retrun nil if
they both match.
:key, :test, :start1, end1, :start2,
end2, from-end will also work here.

(mismatch "confusing" "tripping" :from-end t)
(mismatch "homer" "gomer" :from-end t)
This one is tricky:
It returns the index of the FIRST sequence [confusing]
where the similarities begin, in the first case that
happens to be the 'i' of confusing.
In the second it is the 'o' in homer.

(every #'oddp #(3 4 5 6 7))
Returns nil if all are not odd

(every #'oddp #(3 5 7 9))
Returns True 't' if all are odd

(some #'oddp #(3 4 5 6 7))
Returns t if some are odd

(some #'oddp #(2 4 6 8))
Returns nil if none are odd

(notany #'oddp #(1 3 6 9))
Returns nil if any are odd

(notany #'oddp #(2 4 6 8))
Returns true if none are odd

(notevery #'oddp #(3 4 5 6 7 8))
Returns true if every one is not odd

(notevery #'oddp #(3 7 9))
Returns nil as soon as it sees the
first odd number.

(every #'< #(2 4 6 8) #(3 5 7 9))
Compares each element of the first
sequence to the second to see if
it is less, if so it returns true

(every #'< #(5 6 7 8) #(1 2 3 4))
Same as above, but this would return nil

(some #'< #(7 8 9 10) #(4 5 11 8))
Returns true since 9 is less than 8

(some #'< #(7 8 9 10) #(5 6 7 8))
Returns nil since none of the elements
in the first sequence are less than
the matching elements in the second
sequence

(notany #'< #(4 5 6 7) #(2 3 4 9))
Not any of these are less than any of these.
Returns nil in this case because 7 is less
than 9

(notany #'< #(6 7 8 9) #(5 6 7 8))
Returns true since not any of the first
sequence are less than the matching
element in the second one.

(notevery #'< #(1 2 3 4) #(0 1 2 3))
Returns true becuase not all elements
in first sequence are less than the
matching element in the second.

(notevery #'< #(1 2 3 4) #(2 3 4 5))
Returns nil

(map 'vector #'* #(1 2 3 4 5) #(1 2 3 4 5))
This map multiplies each element in the
first sequence with the matching in the
second. 'vector tells it what kind of
sequence to create.

(setq c (list 2 4 6 8) d (list 1 3 5 7))
(map-into c #'+ c d)
Map-into creates a new sequence, in this
case by adding 'c' and 'd' and stuffing
them in 'c'.

(setq ages (list nil nil nil))
(setq born (list 1923 1965 1977) death (list 1975 1990 2012))
(map-into ages #'- death born)



(setf germ '("nasty" "nappy" "no"))
(second germ)
(setf (second germ) "ooooooOH")
germ
Set a list then change the second value of the list


(round 3.2)
Return rounded number and then return the remainder


(defstruct are-you-my-mommie
           name
           birthday 
           measurements
           height
           weight
           sign)
Define a Structure. Structures are useful for any data
that will change over time. (ex: like age)


(defparameter *nyomi-marcela* (make-are-you-my-mommie
                                :name "Nyomi Marcela"
                                :birthday "June 22, 1980"
                                :measurements "34B-22-33"
                                :height "162 cm"
                                :weight "106 lbs"
                                :sign "Cancer"))
Create instance of a structure

(are-you-my-mommie-sign *nyomi-marcela*)
(setf (are-you-my-mommie-weight *nyomi-marcela*) "105 lbs")

(defparameter *did-her* #S(ARE-YOU-MY-MOMMIE
                            :NAME "Nyomi Marcela"
                            :BIRTHDAY "June 22, 1980"
                            :MEASUREMENTS "34B-22-33"
                            :HEIGHT "162 cm"
                            :WEIGHT "106 lbs"
                            :SIGN "Cancer"))
Structures are good to store data that is going to mutate


(length '(x y z))
(length "kat")
(length (make-array 9))
Get the length of a string, array, and list

(find-if #'numberp '(x y z 3 2 1))
Find first value that satisfies a predicate (ex: numberp)

(count #\t "ribbitribbit")
Count occurences

(position #\b "treebug")
Shows location

(some #'numberp '(q r s 6 5 4))
Do some of the values match a predicate

(every #'numberp '(1 2 3 4 5))
Does every value match predicate

(reduce #'+ '(23 5 69 42 13))
Reduce sequence to a single result by iterating through it
Reduce can use keywords such as:
:initial-value , :key, :from-end, :start, :end

(reduce (lambda (highest num)
          (if (and (oddp num) (> num highest))
            num
            highest))
        '(1 2 3 4 5 6 7 8 9 10)
        :initial-value 0)
Use reduce to find highest odd number

(reduce #'max #(22 1 20 10))
Find max value

(map 'list
     (lambda (x)
       (if (eq x #\b)
         (char-upcase x)
         x))
     "All your base are belong to us!")
Use map to go through string converting it to a list
of characters and changing all letter b's to uppercase

(map 'string
     (lambda (x)
       (if (eq x #\b)
         (char-upcase x)
         x))
     "All your base are belong to us!")
Same as above, except returns a string


(subseq "lemondrop"  3 8)
Pulls out a sequence from start to end values

(sort "x9!3?b%w6_h+2" #'char-lessp)
Sort string by lowest value

(sort '(9 2 4 6 32 23) #'>)
Sort using greater than function

(numberp 23)
Check to see if value is a number
A few others are: arrayp, characterp, consp, functionp,
hash-table-p, lisp, stringp, symbolp (these are type-predicates)

(defun add (a b)
  (let ((x (+ a b)))
    (format t "The sum is ~a" x)
    x))
(add 20 33)
Create a function to add two numbers

(defun addnls (x y)
  (cond ((and (numberp x) (numberp y)) (+ x y))
        ((and (listp x) (listp y)) (append x y))
        ((and (stringp x) (stringp y)) (concatenate 'string x y))))
Create function addnls that takes two arguments and checks if they
are numbers, if so adds them. If lists it appends them. If strings
it concatenates them. Using defmethod would be a better way to write this.


(defmethod add-td ((x number) (y number))
  (+ x y))
(defmethod add-td ((x list) (y list))
  (append x y))
(defmethod add-td ((x string) (y string))
  (concatenate 'string x y))
Defmethod allows the compiler to see the type of the arguments.
It is used to define multiple versions of a function to be used
on different types [type dispatching, based on arguement types].

(defparameter *closure*
  (let ((rawr 0))
    #'(lambda () (setf rawr (1+ rawr)))))
(funcall *closure*)
(funcall *closure*)
(funcall *closure*)
An example of a closure changing the value of rawr

(tagbody
  top
  (print 'meow)
  (when (plusp (random 10)) (go top)))
Using tagbody to loop.

(dotimes (i 4)
  (princ "Wait! Come back <-")
  (fresh-line))
Loop that prints four times

(dotimes (dice 20)
  (let ((roll (random 40)))
    (print roll)
    (if (> roll 20) (return))))

(dotimes (i 5) (print "High five") (princ i))

(dotimes (i 12)
  (princ (random 5))
  (princ " "))
Print out 12 random numbers between 0 and 5

(dotimes (x 21) (format t "~d " x))
Count from 0 to 20

(dotimes (x 12)
  (dotimes (y 12)
    (format t "~d x ~d = " (1+ x) (1+ y))
    (format t "~d " (* (1+ x) (1+ y))))
  (format t "~%"))
Multiplication table 1-12

(dotimes (x 20)
  (dotimes (y 20)
    (format t "~3d " (* (1+ x) (1+ y))))
  (format t "~%"))
Products of multiplication tables 1-20

(defun count-upto (max)
  (let ((result nil))
    (dotimes (i max)
      (push i result))
    (nreverse result)))
(count-upto 20)
Count up to 20

(defun count-upto (max)
  (loop for i below max collect i))
(count-upto 20)
Count up to 20

(dolist (kitty-goes '("meow" "mew-mew" "mao" "rawr"))
  (print kitty-goes))
Loop across list items.

(dolist (kitty-goes '("meow" "mew-mew" "mao" "rawr"))
  (print kitty-goes)
  (if (equal kitty-goes "mao") (return)))
Break out of a do list with return

Dotimes and dolist are simple and use only
one loop variable. "Do" is more powerful/general
can bind as many variables as you want, and gives
complete control over how you can step through them.

(dotimes (x 30)
  (do ((n 0 (1+ n))
       (cur 0 next)
       (next 1 (+ cur next)))
    ((= x n) (print cur))))
Prints the first 30 fibonacci numbers
Do.

(do ((i 0 (1+ i)))
  ((>= i 10))
  (print "which number?")
  (princ i))
Print with do.

(do ((i 5 (1- i)))
  ((> (get-universal-time) (+ (get-universal-time) i)))
  (format t "Exiting in: ~d~%" i)
  (sleep 1))
Do count down from 5.

(do ((num nil) (i 1 (1+ i)))
  ((> i 10) (nreverse num))
  (push i num))
Count to 10

(do ((x 1 (+ x 1))
     (y 1 (* y 2)))
  ((> x 5) y)
  (print y)
  (print "getting closer to the end"))

(loop for count-up from 1 to 20 collecting count-up)
Count to 10 by looping and collecting the numbers.

(loop for sums from 1 to 10 summing (expt sums 2))
Square the first 20 numbers and add them up.

(loop for vowels across "All your base are belong to us!"
      counting (find vowels "aeiou"))
Use loop to count vowels in a sentence.

decf
Variant of setf that subtracts from a variable

(type-of 'pickles)
(type-of 10)
(type-of "nada lada")
Type-of finds the type of a value


(time (dotimes (i 100) (princ "test:") (princ i) (princ " ")))
The time command can be used for timing your code


(loop for i
      below 10
      sum i)
Example using loop macro

(loop for i
      from 10
      to 20
      sum i)
Loop with 'from' to 'to'

(loop for i
      in '(10 20 30 40 50 60 70 80 90 100)
      sum i)
Loop using 'in' to iterate through a list

(loop for i
      below 30
      do (princ i))
Example of do'ing' something in a loop

(loop for i
      below 31
      when (evenp i)
      sum i)
Only do stuff 'when' it meets a certain criteria
In this case: 'when' it is even

(loop for i
      from 10
      to 2000
      do (print i)
      when (= i 15)
      return 'CrazyCodeStopNow!)
Break out of loop with 'return' 'when'

(loop for i
      in '(1 3 5 7 9)
      collect (* i i))
'Collect' values into a list

(loop for x below 12
      for y below 12
      collect x
      collect y)
Mulitple 'for's in one loop and incrementing there values
at the same time. [They do not loop independently, lowest
value exits the loop]

(loop for x below 12
      for y below 12
      collect (* x y))
Same as above except mulitpling the collected values

(loop for x from 1 to 12
      collect (loop for y from 1 to 12
                    collect (* x y)))
Nested loop going through multiplication table products 1-12

(loop for i
      from 1
      for month
      in '(jan feb mar apr may jun jul aug sep oct nov dec)
      collect (cons i month))
Collect months and their number value in a dotted-list

(loop repeat 8
      do (print "Could you repeat that?"))
Repeat loop

(loop initially
      (print "Wait! I don't even know your name yet...")
      for x below 6
      do (print "Say my name %!+(&"))
Give an initial duty before looping through the rest

(loop for x below 4
      do (print "Oh... Don't stop!")
      finally
      (print "What! You are finished!"))
Give a final expression after you do the dues


(loop initially
      (print "If I had a nickel for...")
      for x below 7
      do (print "Cha ching")
      finally
      (print "I'm rich!"))
Initially and finally in same loop


(loop named first-loop
      for i from 1 to 3
      do (print i)
      do (princ "first loop")
      (loop named second-loop
            for j from 1 to 3
            do (print j)
            do (princ "second loop")
            when (= j 2)
            do (return-from second-loop 'exited-second-loop)))
Loops can be 'named' and then broken out of with 'return-from'.
In this case the second-loop never gets to print out it's third line.
Although it is broken out of, it never prints 'exited-second-loop
for some reason. Maybe cause the 'first-loop' keeps going and
keeps calling the second-loop again.

(loop named first-loop
      for i from 1 to 3
      do (print i)
      do (princ "first loop")
      (loop named second-loop
            for j from 1 to 3
            do (print j)
            do (princ "second loop")
            when (= i 2)
            do (return-from first-loop 'exited-first-loop)))
Exits from the first loop returning EXITED-FIRST-LOOP


(loop for i in '(1 3 5 7 9 10 12 13 15 17)
      while (oddp i)
      do (print "Yep! I'm still an odd ball: ")
      do (princ i))
This loop will run as long as it comes across an odd number

(loop for i
      from 0
      do (print "I'm not high enough yet: ")
      do (princ i)
      until (> i 9))
'Until' this loop has i greater than 9, keep going


(loop with x = (* 2 2)
      repeat 6 
      do (print x))
Example of using 'with' to set an auxiliary variable in a loop


(defparameter cookie-jar (make-hash-table))
(setf (gethash 'oreo cookie-jar) "yucky")
(setf (gethash 'chocolate-chip cookie-jar) "yummy")
(setf (gethash 'oatmeal cookie-jar) "ugh")
(loop for person being each hash-key of cookie-jar
      using (hash-value tasted)
      do (print (cons person tasted)))
Loop through hash table with 'being' , 'each', 'using'
When using 'each' 'hash-key' is singular


(defparameter tv-shows (make-hash-table))
(setf (gethash 'Breaking-Bad tv-shows) 10)
(setf (gethash 'Shameless tv-shows) 10)
(setf (gethash 'Arrow tv-shows) 5)
(setf (gethash 'Hell-on-Wheels tv-shows) 7)
(setf (gethash 'The-Walking-Dead tv-shows) 7)
(loop for series being the hash-keys of tv-shows
      do (print series))
(loop for rating being the hash-values of tv-shows
      do (print rating))
Loop through hash table with 'being' 'the'
When using 'the' 'hash-keys' is plural


(loop for i from 0
      do (print i)
      when (= i 5)
      return 'yippy!)


(loop as x from 2 to 10
      collect x)
Collects x into a list


(loop for i
      in '(200 125 75)
      sum i)
Sums the numbers in the list


(loop for x
      on '(10 20 30)
      do (print x))

(loop for i from 2 to 18
      by 2
      do (print i)
      sum i)
Count by 2 and sum them


(loop repeat 6
      for x = 18.0
      then (/ x 2)
      collect x)


(loop for i
      upfrom 4 to 12
      do (print i)
      sum i)


(loop for i from 4
      upto 12
      sum i)


(loop for i
      downfrom 10 to 0
      do (print i))


(loop for i from 10
      downto 3
      do (print i))


(loop for i
      across #(20 40 60)
      sum i)
Loop 'across' an array


(loop for i
      in '(4 12 77 1 -23)
      minimize i into lowest
      maximize i into biggest
      finally (return (cons lowest biggest)))
'Into' lets variable be created, that can be returned 


(loop for i below 12
      unless (oddp i)
      do (print i))
Print out even numbers using 'unless'


(loop for i below 15
      if (oddp i) do (print i))
Print out odd numbers below 15 with 'if'


(loop for i below 15
      when (oddp i) do (print i)
      when (evenp i) do (print "me not odd"))
'When' odd print number, when even print me not odd


(loop for i below 12
      sum i)
Sum the numbers below 12


(loop for i
      in '(5 6 7 2 3 4 8 9)
      minimize i)
Set i to the lowest number in list


(loop for i
      in '(99 77 23 32 0 55)
      maximize i)
Set i to max number in list


(loop for i
      in '(4 6 8 10 12 14)
      always (evenp i))
Check if all items in list are 'always' even


(loop for i
      in '(4 6 8 10 12 14)
      never (oddp i))
Make sure items in list are 'never' odd


(loop for i
      in '(53 2324 4737 23723 324)
      thereis (oddp i))
Check to see if 'thereis' and odd number


(loop for x below 6
      when (= x 4) do (print "i am four")
      and do (print "I like fours!")
      do (print "I wish I was always a four"))
Loop with 'and'


(loop for i below 10
      if (oddp i) do (print i)
      else do (print "I'm even yo..."))
Loop with an 'else'


(loop for i below 8
      when (oddp i) do (print i)
      end
      do (print "yo you!"))
Use 'end' to denote to stop when clause


(loop for i below 12
      append (list 'y i))
'Append' to list inside loop

(loop for i below 12
      nconc (list 'y i))
'Nconc' a list inside a loop


***iterate


(resolve-host-ipaddr "www.heebeejeebeeweeneee.com")
(resolve-host-ipaddr "8.8.178.110") 
Returns :name :aliases :addr-list :addr-type
This may only be in some lisp implementations,
It was working in clisp under cygwin, but not
sbcl under windows.


(write-to-string 127 :base 16)
(format t "~X" 127)
(format nil "~x" 127)
Convert the decimal 127 to hexidecimal
The 2nd uses format

#xf
Hexadecimal 15. Just like you can type
15 at the repl and 15 will be printed
back, you can type #f and 15 will be
printed back. (hexadecimal numeric literal)

(format t "0x~2,'0x" 10)
Decimal to hex outputting 0x in front of number
and padding to two charcters.

(format t "0x~(~2,'0x~)" 127)
Decimal to hex, force hex output to be lowercase
with ~(

(format t "0x~{~2,'0x~^~}" (list 127 0 0 1))
(format t "0x~{~2,'0x~^~}" '(127 0 0 1))
Takes a list of ip quadrants and turns them to
there hex value

(format t "http://0x~{~2,'0x~^~}" '(127 0 0 1))
Spits out an ip in hex form, that can be used
in a browser's url bar.

(defun dec-to-bin (x &optional (callback #'princ))
  (unless (= x 0)
    (dec-to-bin (floor x 2) callback)
    (funcall callback (mod x 2))))
(dec-to-bin 900)
Decimal to binary


(defun dec-to-oct (x &optional (callback #'princ))
  (unless (= x 0)
    (dec-to-oct (floor x 8) callback)
    (funcall callback (mod x 8))))
(dec-to-oct 900)
Decimal to octal


(output-stream-p *standard-output*)
Check to see if standard output is a valid stream for lisp

(input-stream-p *standard-input*)
Check to see if standard input is a valid stream

(write-char #\z *standard-output*)
Write a char to chosen output stream

(read-char *standard-input*)
read first char from repl

(print 'Yabba-dabba *standard-output*)
You can explicitly tell print to send to std-out

(with-open-file (whos-stream "write-test.txt" :direction :output)
 (print "who data dis be?" whos-stream))
Write to file with a file output stream, and print to that stream.

(with-open-file (whos-stream "write-test.txt" :direction :input)
 (read whos-stream))
Read file with input stream
'With-open-file' is a high level way of working with files in which
you do not have to worry about closing the files or corrupting them.


(let ((desired-figure '((bust . 34)
                        (waist . 24)
                        (hips . 36))))
  (with-open-file (my-stream "write-test.txt" :direction :output)
    (print desired-figure my-stream)))
Write a cons list to a file. [alist / association list /cons list]

(with-open-file (my-stream "write-test.txt" :direction :input)
  (read my-stream))
Read from file

(with-open-file (yo-stream "write-test.txt" :direction :output :if-exists :error)
  (print "nada wanna" yo-stream))
Try to write a file, if it already exists, error out

(with-open-file (pee-stream "write-test.txt" :direction :output
                                             :if-exists :supersede)
  (print "I am the over writer" pee-stream))
Explicilty tell it to overwrite file, if it already exists.


(defparameter peeing-in-a-stream (make-string-output-stream))
(princ "You can pee into a string-stream. " peeing-in-a-stream)
(princ "So can your buddies! " peeing-in-a-stream)
(get-output-stream-string peeing-in-a-stream)
Create a string stream. Print to it twice. Then
output what was written to it.

(with-output-to-string (*standard-output*)
  (princ "A large pizza has 8 slices. ")
  (princ "Eat 2 slices, and you will have ")
  (princ (- 8 2))
  (princ " slices left"))
Using 'with-output-to-string' macro to capture text and
redirect it to a string stream, and then print everthing.
Can be more efficient then using concatenation. This
breaks functional programming style, although it can
be useful for debugging.

(defparameter *call-me-baby* (lambda ()
                               "ok"))
(funcall *call-me-baby*)
Closure example


(defparameter *call-me-baby* (let ((x "oh daddy..."))
                               (lambda ()
                                 x)))
(funcall *call-me-baby*)
Closure example

(let ((line-number 0))
  (defun print-slave (x)
    (print line-number)
    (print x)
    (incf line-number)
    nil))
Use closure to keep up with a letted line-number
to know what line number it is on even though
no longer in the let.

;;; Memoization remembers previosly called arguments
;;; and their result. Only works on functional style
;;; code

(get-universal-time)
Show seconds since 1900, determined by system time.

(/ (get-universal-time) 365.0 24 60 60)
Show how many years since 1900 till now

(get-decoded-time)
Breaks down time as:
second, minute, hour, date, month, year, day, daylight-p, zone
The last three are:
day = weekday [0 = sunday]
daylight-p = daylight savings true/false
zone = timezone [6 = central/cdt]


(defun unit-test-mult ()
  (and
    (= (* -3 4) -12)
    (= (* 2 4 6) 48)
    (= (* -8 -8) 64)))
Function that acts as a simple unit test.
Returns T if all tests pass, else
returns NIL.

;;;;;;;;;;;;;;;;;;
;; Recursion notes
;; Notes taken through the little lisper/schemer,
;; seasoned/reasoned   


;; Define ami? as in am I an atom?
;; so it can be used.
(defun ami? (x)
  (not (listp x)))

;; Test to see if atom works
;; Are these atoms?
(ami? (quote ()))

(ami? 'atom)
(ami? (quote an-atom))
(ami? "a chicken atom?")
(ami? 2023)
(ami? #\i)
(ami? '*xyz^!)

;; Are these lists?
(listp 'eve)

(listp '(eve))
(listp '(Who came first adam or the caveman?))

;;end-recursion-notes
;;;;;;;;;;;;;;;;;;;;;



Useful built-in functions
-------------------------
(gensym)
Used to create random/crazy variable names as to make
sure they will not clash with any other variables.
Useful for creating throw away dynamic variables, like
in a macro.  They start with #: and lisp will not let
you use them directly, by name.

An example:
(defmacro split-list (value yes no)
  (my-let g-fun (gensym)
          `(my-let ,g-fun ,value
                   (if ,g-fun
                     (let ((head (car ,g-fun))
                           (tail (cdr ,g-fun)))
                       ,yes)
                       ,no))))

(my-let x 100
        (split-list '(10 30)
                    (+ x head)
                    nil)

(split-list (progn (princ "I'm Lost! ")
                   '(5 9))
            (format t "Splits into ~a and ~a." head tail)
            (format t "Not splitable!")

end-useful-built-in-functions
-----------------------------


Glossary
--------
Anaphoric Macros - Macros that automatically generate variables

Let over lambda - a lexical closure

Tail Call - When a function in lisp calls itself [or another function]
            as it's very last action.

Variable Shadowing - Hiding one variable with another through precedence



end-glossary
------------


Socket streams in clisp
-----------------------

Send a message from one clisp to another, on same or
seperate computer. Open two clisps one to act as server
and the other to act as a client.


(defparameter walkie-talkie-socket (socket-server 3232))
Open socket on server port 3232
Done on server 

(defparameter walktalk-stream (socket-accept walkie-talkie-socket))
Locks up socket and wait for a client connection
Done on server

(defparameter walktalk-stream (socket-connect 3232 "127.0.0.1"))
Connect to server ip and port. Now walktalk-stream can be seen
on both the server and client
Done on client

(print "Serve me the good stuff" walktalk-stream)
Print a message to the walktalk-stream
Done on client

(read walktalk-stream)
The server can read the message 
Done on server

(print "Pay up front for the good stuff!" walktalk-stream)
Send a message back to client
Done on server

(read walktalk-stream)
Read message from server
Done on client

(close walktalk-stream)
Make sure to close the stream on both client and server
Done on both client and server

(socket-server-close walkie-talkie-socket)
Close the socket on the server, else port will be locked up till
reboot.
Done on server

End of socket-stream example
-----------------------------


Lisp Data Types
---------------

Numbers: 321 3.21 -10e2 3/5 #c(2 3)
#c(2 3) = complex numebr
Strings: "Like me"
Symbols: me-a-symbol 'me-too
Lists: (a ("list" "of") '(lists) b c)
Characters: #\D #\e #\f #\space

end-lisp-data-types
-------------------

Special Operators
-----------------

quote   if      progn
let     let*    setq
flet    labels  macrolet
symbol-macrolet
block   return-from   tag body   go
multiple-value-call   multiple-value-bind



quote - prevents evaluation
if - boolean choice operations
progn - ability to sequence a number of forms


end-special-operators
---------------------

(apropos :count-d)
Apropos searches for symbol names

internal-time-units-per-second
Shows the number of internal time units in one second [for current machine] 


Packages
--------
Packages are useful for preventing namespace
conflicts.


*package*
common-lisp:*package*
cl:*package*

:joemammy
keyword:joemammy
(eql :joemammy keyword:joemammy)
Accessing symbols in the current package

(mapcar #'package-name (package-use-list :cl-user))
Display packages inherited by common-lisp-user

(package-name (symbol-package 'package)
(package-name (symbol-package 'joedaddy))
Show which package a symbol is from.

(defpackage :leftoff-books-db
 (:use :common-lisp))
Define a new package and inherit from the common lisp package.

(in-package :leftoff-books-db)
Use the new package

(defpackage #:leftoff-books-db
 (:use #:common-lisp))
Define a package without interning

(in-package :cl-user)
Switch back to the default package of the repl.

(defpackage :leftoff.text-db
  (:use :common-lisp)
  (:export :open-db
           :save-db))
Export symbols in your package

(defpackage :left-off.user-db
  (:use :common-lisp :leftoff.text-db)
  (:import-from :mysql.plugin :dbrow-to-html))
Import individual symbol from a package.

(defpackage :leftoff.books-db
  (:use
    :common lisp
    :leftoff-text-db
    :mysqlite.plugin)
  (:import-from mysqlite.plugin :dbrow-to-html)
  (:shadow :looprow))
Exclude a symbol from a package with ":shadow".



end-packages
------------

Lisp Tools
----------

quicklisp
---------

quicklisp - Common Lisp library manager.

To install quicklisp:
curl -O http://beta.quicklisp.org/quicklisp.lisp
sbcl --load quicklisp.lisp
(quicklisp-quickstart:install)

quicklisp commands:
(quicklisp-quickstart:help)
Display Help

(ql:quickload "system-name")
Installs a library 

(ql:quickload '(cl-who hunchentoot parenscript))
To install several libraries at once.

(ql:system-apropos "term")
Search for a library 

(ql:add-to-init-file)
Add quicklisp to init file, so it loads on lisp startup.
Adds to: ~/.sbclrc

end-quicklisp
-------------

CL-WHO - library for converting Lisp expressions to XHMTL.
Hunchentoot - Common Lisp webserver / toolkit for dynamic web sites.
Parenscript - Compile lisp expressions into javascript.

end-lisp-tools
--------------


Slime related
-------------

^c ^d h loop
Query Common Lisp Hyperspec (CLHS). In this case for: loop

^q,
To insert a comma on a previously evaluated line.
[comma is slime command, that normally only works
as first character, but if evaluated already
it may eat you]

C-M-q
Reindent an expression from the opening parenthesis

C-c M-q
Reindent from within the body of a function

C-c RET
Do this on the open paranthesis of a macro and it will
run slime-macroexpand-1. Which runs macroexpand-1
pretty printed.

,
Enter a command to slime.

,change-package
Change a package within slime.

end-slime-related
-----------------

Various Lisp Links: ^

 
Interesting articles
--------------------
The Nature of Lisp
http://www.defmacro.org/ramblings/lisp.html


Various resource links
----------------------
The common lisp wiki (has all kinds of links and resources)
http://www.cliki.net/

A page with a bunch of links and resources
http://www.apl.jhu.edu/~hall/lisp.html

clisp.org resources page
http://www.clisp.org/resources.html

Common Lisp Implementations: A Survey
http://common-lisp.net/~dlw/LispSurvey.html

Sockets [Network] are not part of ANSI-CL
Here are two attempts at providing one:
http://common-lisp.net/project/usocket/
http://common-lisp.net/project/cl-sockets/


Interactive tutorials
---------------------
ELM-ART interactive online lisp tutorial
http://art2.ph-freiburg.de/Lisp-Course

Lisp Tutor Jr (link is dead, maybe find a new one)
http://reed.cs.depaul.edu/peterh/Tools/lisptutor.html


Tutorial / Guides
-----------------
http://cs.gmu.edu/~sean/lisp/
Tutorials and Assorted Lisp Stuff (look for this section)


Pascal Costanza's Highly Opinionated Guide to Lisp
http://www.p-cos.net/lisp/guide.html

Lisp Primer
http://mypage.iu.edu/~colallen/lp/

Sample Code and exercises
http://www.dynamiclearningcenter.com/

AI Programming in Lisp
https://www.scm.tees.ac.uk/isg/website/index.php?page=lecture_sc

http://www.ic.unicamp.br/~meidanis/courses/mc336/2006s2/funcional/L-99_Ninety-Nine_Lisp_Problems.html
http://www.informatimago.com/develop/lisp/l99/
L-99: Ninety-Nine Lisp Problems


Online Books
------------
Lisp Web Tales (Short book on lisp web dev)
http://lispwebtales.ppenev.com/

http://www.gigamonkeys.com/book/
Practical Common Lisp -Seibel

http://www.cse.buffalo.edu/~shapiro/Commonlisp/
Common Lisp: An Interactive Approach

http://www.cs.cmu.edu/~dst/LispBook/index.html
Common Lisp: A Gentle Introduction to Symbolic Computation

Successful Lisp: How to Understand and Use Common Lisp
http://www.psg.com/~dlamkins/sl/

Common Lisp the Language, 2nd Edition 
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node1.html

Basic Lisp Techniques
http://www.franz.com/resources/educational_resources/cooper.book.pdf

The Common Lisp Cookbook
http://cl-cookbook.sourceforge.net/

On Lisp
http://www.paulgraham.com/onlisptext.html

Lisp Outside the Box  (an abandoned book about 1/4 complete, started in 2009)
http://lisp-book.org/


Books to Buy
------------
Land of Lisp
Even if you don't have the book,
you can check out most of the source code:
http://landoflisp.com/source.html

Artificial Intelligence: A Modern Approach
Paradigms of Artificial Intelligence Programming:
ANSI Common Lisp
Principles of Biomedical Informatics (most code in lisp)

Random Info
-----------
http://c2.com/cgi/wiki?search=lisp
http://plob.sourceforge.net/
http://www.lispworks.com/documentation/HyperSpec/Front/index.htm
http://hyperpolyglot.org/lisp

ANSI and GNU Common Lisp Document
http://www.mat.uc.pt/~pedro/cientificos/funcional/lisp/gcl_toc.html

Videos
------
Franz developers of Allegro CL have training videos:
http://www.franz.com/services/classes/download.lhtml

Structure and Interpretation of Computer Programs
MIT's course using scheme
http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/

http://www.coursehero.org/lecture/introduction-lisp
Introduction to Lisp (Havard CS1) [23 videos is on Lisp]

An Brief Introduction to Lisp (pt 1-4) [Oreilly]
http://www.youtube.com/watch?v=M-BFgErib4k
http://www.youtube.com/watch?v=jvnwXHsL8eo
http://www.youtube.com/watch?v=xfh-oXjS73I
http://www.youtube.com/watch?v=g_RjV5Q3sTY

Lisp Screencast 01: Macros
http://www.adztec-independent.de/2009/01/lisp-screencast-01-macros/


Introduction to Artificial Intelligence (ASU-FEAS)
http://rakaposhi.eas.asu.edu/cse471/
(Has 3 videos on lisp)
-------------------------------
Lecture 1 on the anatomy of lisp:
http://www.youtube.com/watch?v=Ot1CgsETQCc
http://rakaposhi.eas.asu.edu/cse471/lisp-anatomy.avi

Lecture 2 on functions as first-class objects:
http://www.youtube.com/watch?v=Sfa1lBNZ6zQ
http://rakaposhi.eas.asu.edu/cse471/lisp-functions-are-first-class.avi

Lisp Recitation lecture by Will Cushing ([Jan 12, 2012]):
http://rakaposhi.eas.asu.edu/cse471/cse471-s12-lisp-recitation-will.MP4


Lisp IDEs
--------------
http://www.daansystems.com/lispide/
LispIDE


Useful Libraries
----------------
Linedit 
Provides better line-editing in the REPL
http://common-lisp.net/project/linedit/


EmacsLisp
---------
An Introduction to Programming in Emacs Lisp
http://www.gnu.org/software/emacs/manual/html_mono/eintr.html


Lisp Repositories
-----------------
CMU Common Lisp Repository
http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/lang/lisp/0.html

http://www.cs.cmu.edu/Groups/AI/html/faqs/lang/lisp/part1/faq.html

^

default