CS 227 lecture -*- Outline -*- Focus on: the "recursive moment": how to see the "dragon's 3 steps". * recursion ** problem we can now write procedures that do different things with their output, but we can't yet repeat something any number of times, ** stories tell the story about being distracted and not wanting to slice a loaf of freshly baked bread, but slicing one slice off several loaves of bread, until it was all sliced then going grocery shopping: I'll get the first thing on the list, you be responisble for the rest then in the checkout line: I can't add all these numbers, I have to think about recursion..., but 1 can add one price to the price of a cart's worth (write down things to remember for the other carts) ** the idea -------------- PHILOSOPHY OF RECURSION On ending: * All good things must come to an end On starting: * A thousand mile journey begins with a single step. How to live life: * One day at a time * Sieze the Day On worrying: * Today's trouble is enough for today. * Don't be anxious about tomorrow. * Tomorrow will take care of itself -------------- Translate this into code days as a list (born day2 ... dying) () <-- Lincoln define today, future, and living (one day at a time) define value of life (arbitrarily) summing up value of each day ** initial example ------------- A PROBLEM (add1-to-each '()) ==> () (add1-to-each '(2 3 4)) ==> (3 4 5) (add1-to-each '(2 6 8 -1 9 1 2 4 5 7 9)) ==> (3 7 9 0 10 2 3 5 6 8 10) PLAN TYPE: (-> ((list number)) (list number)) (define add1-to-each (lambda (ls) ; if ls is empty, return () ; else add 1 to car of ls ; cons that onto ; the result of add1-to-each of ; cdr of ls)) TRANSLATION (define add1-to-each (lambda (ls) (cond ((null? ls) '()) (else (cons (add1 (car ls)) (add1-to-each (cdr ls))) )))) ------------ perhaps best to put the above on the board... ** why we need recursion, and what it is. ---------- SNOC add an item to the end of a list (snoc '() 'a) ==> (a) (snoc '(a) 'b) ==> (a b) (snoc '(1 2) 3) ==> (1 2 3) snoc: (-> ((list T) T) (list T)) ALGORITHM? if list is empty, cons new item onto '() if list has 1 item, cons new item onto '() and cons car onto that if list has 2 items, cons new item onto '() and cons cadr onto that and cons car onto that ... ----------- can translate the plan to code but shows the problem this plan is unworkable! (Scheme doesn't do ...) what are the problems? can't write it all down lots of redundancy how did we eliminate writing the same thing twice before? used helping procedures but what other procedures have we got that can help? none so this procedure will have to help itself such procedures are called recursive they have the advantage of being able to do an indefinite amount of work. ------------- RECURSIVE PROCEDURES def: a procedure is recursive if it uses itself as a helping procedure. RECURSIVE DEFINITION OF snoc (snoc '() item) = (cons item '()) (snoc (cons x l) item) = (cons x (snoc l item)) IS IT CORRECT? (snoc '() 'a) = (cons 'a '()) ==> (a) (snoc '(a) 'b) = (snoc (cons 'a '()) 'b) = (cons 'a (snoc '() 'b)) = (cons 'a (cons 'b '())) ==> (a b) -------------- why does the recursive definition work? by induction on (length or) structure of lists (do this both forwards and backwards) The recursive definition corresponds to the a new plan -------------- NEW PLAN base case: if list is empty, cons new item onto '() recursive case: (if list is not empty) cons the car of list onto snoc of (cdr list) and the item -------------- develop the code for this on the board (DEFINE snoc (LAMBDA (lst item) (IF (null? lst) (cons item '()) (cons (car lst) (snoc (cdr lst) item))))) why does it stop? stops on empty list by inspection of code length of non-empty list is always greater than 0 each recursive call decreases the length can't both decrease and remain greater than 0 forever ** more examples *** copy this is THE standard paradigm, the simplest recursion ------------- WRITE THIS YOURSELF (copy '()) ==> () (copy '(1 2 3 4 5)) ==> (1 2 3 4 5) (copy '(a b c)) ==> (a b c) copy: (-> ((list T)) (list T)) ------------- note can't just handle these cases *** rac following is last-item in the book ------------- RAC (rac '(1)) ==> 1 (rac '(1 2)) ==> 2 (rac '(1 2 3)) ==> 3 (rac '(a b c surprise)) ==> surprise rac: (-> ((list T)) T) ------------ add an item to the tail of a list rac of empty list is an error how do we know when to stop? put an answer on the board with REQUIRES: ls is not empty *** more examples to work in class -------------- MORE EXAMPLES (member? 'x '()) ==> () (member? 'a '(a)) ==> #t (member? 'a '(b c)) ==> #f (member? '(hi) '((a) (hi) (there))) ==> #t member?: (-> (T (list T)) boolean) (remove-1st 'fox '()) ==> () (remove-1st 'fox '(fox hen fox pig)) ==> (hen fox pig) (remove-1st '(duck) '((look out) (duck))) ==> ((look out)) remove-1st: (-> (T (list T)) (list T)) (append '() '(1 2 3)) ==> (1 2 3) (append '(7 9) '(1 2 3)) ==> (7 9 1 2 3) (append '(a b) '(c)) ==> (a b c) ---------------- can also try double (a b) ==> (a a b b) rdc assoc reverse