Historical Overview

Syntax

27
foo
"homoiconic"

Syntax

(print "greeting")

(list "apple" "banana" "orange" "pear")

Cons lists

Cons lists

Cons cell

Image from Zazzle.com

Cons list example

Image from wikipedia.org

Code as data

(let ((x 10)
      (n 5))
  (expt x n))

Code as data

(let ((s5 (sqrt 5)))
  (/ (- (expt (/ (1+  s5) 2) n)
        (expt (/ (- 1 s5) 2) n))))

Image created by Chris Jester-Young

Accessing cons elements

(car (list 1 2))

(cdr (list 1 2))

The Lisp evaluation model

(let ((x (+ 1 2))
      (y (* 2 3)))
  (+ x y))

The Lisp evaluation model

(let ((x 3)
      (y 6))
  (+ x y))

The Lisp evaluation model

  (+ 3 6)

The Lisp evaluation model

   9

Quote and Unquote

Quote and Unquote

   (print foo)

   (let ((foo 1))
     (print 'foo))

Quote and Unquote

Quote and Unquote

(let ((a 'apple))
  (list 'a a `(,a banana orange pear)))

Quote and Unquote

(let ((a 'apple))
  (list 'a a `(,a banana orange pear)))

(a apple (apple banana orange pear))

Control flow

(if (> 7 3)
    (print "yes")
    (print "no"))

Control flow

(if (> 7 3)
    (print "yes")
    (print "no"))

(cond
	((> 7 3) (print "7 greater than 3"))
	((< 7 3) (print "7 less than 3"))
	((= 7 3) (print "7 equal to 3")))

Classic interpreter

(define eval (lambda (form)
   (cond 
      (atom? form) form
      <if p c a> (if (eval p) (eval c) (eval a))
      <f a1 a2 a3> ((eval f) (eval a1) (eval a2) (eval a3))
      ...
)))

REPL

(loop (print (eval (read))))

Recursive functions

(defun process-order-list (order-list)
  (if order-list
      (let ((order (car order-list)))
        (process-order order)
        (process-order-list (cdr order-list)))))

(process-order-list `(a b c))

Higher order functions

(mapcar 'process-order `(a b c)) 

Higher order functions

(reduce '+ (list 1 2 3))

Closures

#'(lambda (a b)
     (+ a b))

Closures

#'(lambda (a b)
     (+ a b))   

#<FUNCTION (LAMBDA (A B)) {1003D75B7B}>

Evaluating Closures

(#'(lambda (a b)
      (+ a b))
 7
 9)   

Nested closures

(defun make-computer-factory (brand)
  #'(lambda (format)
      #'(lambda (cpu-vendor)
          (print (list brand format cpu-vendor)))))

Nested closures

(defun make-computer-factory (brand)
  #'(lambda (format)
      #'(lambda (cpu-vendor)
          (print (list brand format cpu-vendor)))))

(let* ((ibm (make-computer-factory 'IBM))
       (ibm-server (funcall ibm 'SERVER)))
  (funcall ibm-server 'INTEL)
  (funcall ibm-server 'AMD))

(IBM SERVER INTEL)
(IBM SERVER AMD)  

Nested Closures

(defun make-computer-factory (brand)
  #'(lambda (format)
      #'(lambda (cpu-vendor)
          (print (list brand format cpu-vendor)))))

(let* ((dell (make-computer-factory 'DELL))
       (dell-workstation (funcall dell 'WORKSTATION)))
  (funcall dell-workstation 'INTEL)
  (funcall dell-workstation 'AMD))

(DELL WORKSTATION INTEL)
(DELL WORKSTATION AMD)

Mutating closed-over variables

(defun make-account ()
  (let ((balance 0))
    (values
     #'(lambda ()
         balance)
     #'(lambda (amount)
         (setf balance amount)))))

(multiple-value-bind (getter setter)
    (make-account)
  (print (funcall getter))
  (funcall setter 100)
  (print (funcall getter))
  (funcall setter 0)
  (print (funcall getter)))

Mutating closed-over variables

0
100
0

Macros as templates

(defmacro make-named-gate (gate-name)
  `(let ((gate 'closed))
     (defun ,(intern (string-upcase (concatenate 'string "open-gate-" gate-name))) ()
       (setf gate 'open))
     (defun ,(intern (string-upcase (concatenate 'string "close-gate-" gate-name))) ()
       (setf gate 'closed))
     (defun ,(intern (string-upcase (concatenate 'string "show-gate-" gate-name))) ()
       gate)
     ))

Macros as templates

(macroexpand '(make-named-gate "A"))
(LET ((GATE 'CLOSED))                                                                                                                                                                                                                                                                                                           (DEFUN OPEN-GATE-A () (SETF GATE 'OPEN))
  (DEFUN CLOSE-GATE-A () (SETF GATE 'CLOSED))
  (DEFUN SHOW-GATE-A () GATE))

Macros as templates

(make-named-gate "A")
(open-gate-a)
(close-gate-a)

Macros

Macros

with- macros

(with-file f "log.txt"
   (print f "computation started")
   (do-computation)
   (print f "computation complete"))

Object re-orientation

(defclass duck () ())

(defmethod speak ((d duck))
  (print "qwack"))

(speak (make-instance 'duck))

Object re-orientation

(defclass air () ())
(defclass helium () ())

(defmethod speak ((d duck) (a air))
  (print "qwack"))

(defmethod speak ((d duck) (h helium))
  (print "squeack"))

(speak (make-instance 'duck) (make-instance 'helium))

Object re-orientation

(let ((account-balance 100))
  (defmethod withdraw (amount)
    (setf account-balance (- account-balance amount))
    'success)

  (defmethod withdraw :around (amount)
    (format t "balance before ~a~%" account-balance)
    (let ((result (call-next-method amount)))
      (format t "balance after ~a, result ~a~%" account-balance result))))

Object re-orientation

CL-USER> (withdraw 40)
balance before 100                                                                                                                                                                                                                                                                                                            
balance after 60, result SUCCESS

Dynamically scoped variables

(defvar *standard-output*)

(defun main ()
  (format *standard-output* "Outer function~%")
  (let ((str (inner-function1)))
    (format *standard-output* "String was ~s~%" str))
  (format *standard-output* "Outer function done~%"))

(defun inner-function1 ()
  (let ((*standard-output* (make-string-output-stream)))
    (inner-function2)
    (get-output-stream-string *standard-output*)))

(defun inner-function2 ()
  (format *standard-output* "Hello world"))

Dynamically scoped variables

CL-USER> (main)
Outer function
String was "Hello world"
Outer function done

References and further reading

Common Lisp

Practical Common Lisp

On Lisp

Scheme

The Little Schemer

Simply Scheme: Introducing Computer Science

Structure and Interpretation of Computer Programs