From Lambda Calculus to LISP Functional Programming Academic Year Alessandro Cimatti
The LISP Language Proposed by John McCarthy in the late 1950s Based on Lambda Calculus Key concepts –Interpreted language –Dynamic data structures –LISP Procedures as LISP data Basic notions –primitive expressions –combination of simple into compound expressions –abstraction, compound objects are named and manipulated as units
LISP Expressions > > ( ) 531 > ( ) 666 > (* 5 99) 495 > (/ 10 5) 2 > (/ 10 6) > ( ) 12.7 > ( ) 75 > (* ) 1200 The operator is always the leftmost element Parentheses rule out ambiguities
LISP Expressions > (+ (* 3 5) (- 10 6)) 19 > (+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6)) 33
Naming the Environment > (setq size 2) 2 > (setq pi ) > (* pi (* radius radius)) > (setq circumference (* 2 pi radius))
Evaluating Combinations > (* (+ 2 (* 4 6)) ( )) ; (* ( ) ( )) ; (* ( ) 15 ) ; (* ) 390 Any evaluation order is ok (in this simple example)
Evaluating Combinations > (* (+ 2 (* 4 6)) ( )) * *
Compound Functions > (defun square (x) (* x x)) square > (square 21) 441 > (square (+ 2 5)) 49 > (square (square 3)) 81 > (defun ( ) )
Compound Functions > (defun sum-of-squares (x y) (+ (square x) (square y))) sum-of-squares > (sum-of-squares 3 4) 25 > (defun f (a) (sum-of-squares (+ a 1) (* a 2))) f > (f 5) 136
Procedure Application > (f 5) ((λ a.(sum-of-squares (+ a 1) (* a 2)) 5) (sum-of-squares (+ 5 1) (* 5 2)) (sum-of-squares 6 10 ) ((λ x y.(+ (square x) (square y))) 6 10) (+ (square 6) (square 10)) (+ ((λ x.(* x x)) 6) ((λ x.(* x x)) 10)) (+ (* 6 6) (* 10 10)) ( ) 136
Procedure Application > (f 5) (sum-of-squares (+ 5 1) (* 5 2)) (+ (square (+ 5 1)) (square (* 5 2))) (+ (* (+ 5 1) (+ 5 1)) (* (* 5 2) (* 5 2))) (+ (* 6 6 ) (* 10 10)) ( ) 136 The result is the same, but the evaluation process is different! Notice that (+ 5 1) and (* 5 2) are evaluated twice.
Reduction Methods Normal-order evaluation –fully expand body, and then reduce Applicative-order evaluation –evaluate the arguments and then apply –additional efficiency, reduced evaluations More to come…
Conditional Expressions > (defun abs (x) (cond ((> x 0) x) ((= x 0) 0) ((< x 0) (- x)))) abs > (defun abs (x) (cond ((< x 0) (- x)) (else x))) abs > (defun abs (x) (if (< x 0) (- x) x)) abs
Conditional Expressions > (cond ( ) ( )... ( )) > (if )
Logical Operators > (and... ) > (or... ) > (not ) > (and (> x 5) (< x 10)) > (defun >= (x y) (or (= x y) (> x y))) > (defun >= (x y) (not (< x y))
Exercise Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers
A Solution > (defun sos-greatest (x y z) (cond ((and (< x y) (< x z)) (sum-of-squares y z)) ((and (< y x) (< y z)) (sum-of-squares x z)) (else (sum-of-squares x y)))))
Recursion > (defun factorial (n) (if (= n 1) 1 (* n (factorial (- n 1)))) factorial > (factorial 6) (* 6 (factorial 5)) (* 6 (* 5 (factorial 4))) (* 6 (* 5 (* 4 (factorial 3)))) (* 6 (* 5 (* 4 (* 3 (factorial 2))))) (* 6 (* 5 (* 4 (* 3 (* 2 (factorial 1)))))) (* 6 (* 5 (* 4 (* 3 (* 2 1))))) (* 6 (* 5 (* 4 (* 3 2)))) (* 6 (* 5 (* 4 6))) (* 6 (* 5 24)) (* 6 120) 720
Recursion > (defun factorial (n) (f-iter 1 1 n)) factorial > (defun f-iter (res cnt max) (if (> cnt max) res (f-iter (* cnt res) (+ cnt 1) max))) f-iter
Recursion > (factorial 6) (f-iter 1 1 6) (f-iter 1 2 6) (f-iter 2 3 6) (f-iter 6 4 6) (f-iter ) (f-iter ) (f-iter ) 720
Comparison Linear recursive Stack needed Conceptually simpler Iterative Does not need stack State is finite Powerful compilation technique
Fibonacci Numbers The sequence of Fibonacci –Fib(n) = 0 if n = 0, else –Fib(n) = 1 if n = 1, else –Fib(n) = Fib(n – 1) + Fib(n – 2) 0, 1, 1, 2, 3, 5, 8, 13, 21,... > (defun fib (n) (cond ((= n 0) 0) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2))))) fib
Fibonacci: Computation > (fib 5) (+ (fib 4) (fib 3)) (+ (fib 4) (+ (fib 2) (fib 1))) (+ (fib 4) (+ (+ (fib 1)(fib 0)) 1)) (+ (fib 4) (+ (+ 1 0) 1)) (+ (+ (fib 3) (fib 2)) 2) (+ (+ (fib 3) (+ (fib 1) (fib 0))) 2) (+ (+ (fib 3) (+ 1 0)) 2) (+ (+ 2 1) 2) 5
Exercise Tree recursion –Can be very expensive Can we define linear iteration for Fibonacci numbers? Hint –identify the state: we need only the two previous values of the series, say a an b –Initially, a is 1 and b is 0 –At each step, a becomes a + b b becomes a a 1, 1, 2, 3, 5, 8, 13, 21, 34,... b 0, 1, 1, 2, 3, 5, 8, 13, 21,...
Linear Iteration for Fibonacci > (defun fib (n) (fib-iter 1 0 n)) fib > (defun fib-iter (a b cnt) (if (= cnt 0) b (fib-iter (+ a b) a (- cnt 1)))) fib-iter
Exercise Exponentiation –b n = 1, if n = 0 –b n = b * b n-1, otherwise Exponentiation in LISP –using linear recursion –using linear iteration
Exponentiation > (defun expt (b n) (if (= n 0) 1 (* b (expt b (- n 1))))) expt
Iterative Exponentiation > (defun expt (b n) (expt-iter b n 1) expt > (defun expt-iter (b cnt res) (if (= cnt 0) res (expt-iter b (- cnt 1) (* b res)))) expt-iter
Iterative Squaring We have seen –linear recursion –linear iteration Can we do better? –E.g. use only a logarithmic number of steps? Exponentiation also follows these rules –b 2n = (b n ) 2 –b 2n+1 = b * b 2n
Iterative Squaring > (defun fast-exp (b n) (cond ((= n 0) 1) ((even? n) (square (fast-exp b (/ n 2))) (else (* b (fast-exp b (- n 1))))) fast-exp