100 likes | 217 Views
Reminder: if and cond. If and cond are both conditional functions; they both return different values depending on the result of logical tests. (defun abs(X) (if (> X 0) X (* X –1) ) ). If: ( function_name test result_if_true result_if_false ).
E N D
Reminder: if and cond If and cond are both conditional functions; they both return different values depending on the result of logical tests (defun abs(X) (if (> X 0) X (* X –1) ) ) If: ( function_name test result_if_true result_if_false ) (defun abs(X) (cond ( (> X 0) X ) ( t (* X –1) ) ) ) cond: ( function_name test+result_pair test+result_pair ) ( test result_if_true ) ( test result_if_true ) An if call is a simple list with 4 elements. A cond call is a list starting with “cond”, and followed by a series of internal lists. Each internal list contains 2 elements; a test and a result returned if that test it true
Using “t” in cond (defun abs(X) (cond ( (> X 0) X ) ( t (* X –1) ) ) ) A cond call starts with the function name cond followed by a series of lists. Each list is a pair containing two elements: a test, and a result. Cond goes through these lists in order, one at a time. For each list, it tests whether the first element in the list is true. If the first element is true, cond returns the second element in the list and does not go on to the remaining lists. Often the last list in a cond call has a “t” as its first element (where the test would normally be). “t” is always true. If cond gets through all the other lists as far as the last list, the t means it will always return the second element of this list.
And, Or and Not You can use And, Or, and Not in your logical tests for if and cond. These functions combine tests, and return t or nil (if (and (= (first L) 1) (= (first (rest L)) 2) (= (third L) 3) ) … As many tests as you like, each in its own brackets close bracket for and Open bracket for and (if (or (= (first L) 1) (= (first L) 2) (= (first L) 3) ) … As many tests as you like, each in its own brackets close bracket for or Open bracket for or unlike the other two, not can only take a single test as its argument. (if (not (= (first L) 1) ) …
Recursion: count the number of elements in a list This is going to be a loop where we • consider each element of a list (count that element) • when we’ve counted an element, go on to rest of the list • stop when we get to the end of the list Function definition (defun len(L) ) Stopping condition (cond ( ) ) (null L) 0 recursive condition ( t ) (+ 1 ) (len ) (rest L)
How does recursion with lists work? • (defun len(L) • (cond ( (null L) 0 ) • ( t (+ 1 (len (rest L))) ) ) ) • > (len ‘(a b)) 2 2 • 1. Make a copy of the function; replace L by ‘(a b) • (defun len( ‘(a b) ) • (cond( (null ‘(a b)) 0 ) • ( t (+ 1 (len (rest ‘(a b)))) ) ) ) • 2. Evaluate the body of the function • (cond ( (null ‘(a b)) 0 ) • ( t (+ 1 (len (rest ‘(a b))) ) ) ) • 3a. Eval (rest ‘(a b)) • (+ 1(len (rest ‘(a b)) )) • (null ‘(a b)) is false (nil); go to next line and eval (+ 1 (len (rest ‘(a b)))) • 3b. Eval (len ‘(a)) • (+ 1 (len ‘(a)) ) • 3c. Add 1 • (+ 1 1 ) ‘(a) 1 2 3. (null ‘(a) is false (nil);evaluate (+ 1 (len (rest ‘(a)))) • 1. Make a copy of the function and replace L by ‘(a) • (defun len ( ‘(a) ) • (cond ( (null ‘(a)) 0 ) • ( t (+ 1 (len (rest ‘(a)))) ) ) ) • 2. Evaluate the body of the function • (cond ( (null ‘(a)) 0 ) • ( t (+ 1 (len (rest ‘(a)))) ) )) • 3a. Eval (rest ‘(a)) • (+ 1 (len (rest ‘(a)) )) • 3b. Eval (len ‘() ) • (+ 1 (len ‘() ) ) • 3c. Add 1 • (+ 1 0 ) ‘() 0 1 • 3. (null ‘()) is true (t); just return 0 as the answer • ( t 0) • 2. Evaluate the body of the function • (cond ( (null ‘() ) 0 ) • ( t (+ 1 (len (rest ‘())) ) ) • 1. Make a copy of the function and replace L by ‘() • (defun len( ‘() ) • (cond ( (null ‘() ) 0 ) • ( t (+ 1 (len (rest ‘()))) ) )
Sum the elements of a list This is going to be a loop where we • Add the first element of the list • Apply the function to sum up the rest of the list • stop when we get to the end of the list Function definition (defun sum(L) ) Stopping condition (cond ( ) ) (null L) 0 recursive condition ( t ) (+ ) (first l) (sum ) (rest L)
How may arguments does the function need? Stopping condition checks one or many of the incoming arguments, to see if we can stop and compute an answer straight away There can be more than one reason for stopping If we’re not at a stopping condition, we need to recurse. We can do a test to see what we need to do in the recursive call There can be more than one recursive call as well; we might want to do different things (combine the recursive result in different ways, use different smaller args in the recursive call) The answer is computed by some simple (non-recursive) operation on the incoming arguments For different stopping conditions a different answer can be returned. Remember, these answers are passed back to the recursive calls! Design pattern for simple recursive fns (defun MyFn(arg1 arg2….) ) (cond ) ( ) ( stopping-condition1 arg??) ans?? ( ) ( stopping-condition2 arg??) ans?? ( ) ( recursive-test1 args??) (combine arg?? ) (MyFn smaller-args??) ( ) ( recursive-test2 args??) In recursion, we combine one part of the arguments (in some way) (combine arg?? ) (MyFn smaller-args??) with the result of a recursive call to the function with a smaller (in some way) arguments
example with two stopping conditions (member A L) returns t if element A occurs somewhere in list L, and returns nil or ‘() if not. This is going to be a loop where we • go through the list recursively one element at a time • On each loop, check if the first element of the list is A • stop when? 1) we get to the end of the list 2) we find the element A (defun member(A L) ) Function definition (cond ( ) ) (null L) nil Stopping condition1 Stopping condition2 ( ) (equal A ) (first L) t ( t ) (member ) A (rest l) recursive condition
example with two recursive conditions (count A L) counts the number of times element A occurs in list L, and returns that number. Go through the list recursively one element at a time On each loop, check if the first element of the list is A • If the current element is A, add 1 to the recursive answer • If it is not A, simply pass back the recursive answer stop when? When we get to the end of the list (defun count(A L) ) Function definition (cond ( ) ) (null L) 0 Stopping condition ( ) (equal A ) (first L) Recursive condition1 (+ 1 ) (count ) A (rest l) recursive condition2 ( t ) (count ) A (rest l)
general pattern for recursion on lists Each recursive call involves a shortened version of the list (usually (rest L), but can also be (rest (rest L)) etc.) Each call involves some action or comparison on the first element of the list (first L) (or sometimes the first two etc.) One stopping condition is always when the list is empty. There can be other stopping conditions too. Next we will see how to write recursive functions that construct lists. This will use the function cons.