1 / 13

Conditionals and Recursion

Conditionals and Recursion. "To iterate is human, to recurse divine." - L. Peter Deutsch. If, When, Unless. We’ve already learned about LISP’s if construct ( if test then-result else-result) The else-result is actually optional, with a default return value of NIL

ciro
Download Presentation

Conditionals and Recursion

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Conditionals and Recursion "To iterate is human, to recurse divine." - L. Peter Deutsch

  2. If, When, Unless • We’ve already learned about LISP’s if construct (if test then-result else-result) • The else-result is actually optional, with a default return value of NIL • There are also macros for similar conditionals: (when test result) (unless test result) • when returns its result if the test is true, NIL otherwise • unless returns its result when the test is not true, NIL otherwise

  3. Cond • A more useful construct that allows for choosing between multiple conditions is cond (cond (test S-expression*)*) >(cond ((> 5 20) 'wrong) ((< 5 20) 'right) (t 'not-reached)) RIGHT • Good programming style always includes a t condition at the end • Default return value is NIL

  4. Recursion • A function calls itself • An extremely powerful and expressive technique • Easier to do in LISP than in imperative languages (Java, C++), but still challenging at first • Using LISP will give you new respect for and understanding of recursion

  5. Example 1: Height of a Binary Tree (defun tree-height (x) (if (atom x) ;Test 0 ;Base Case (1+ (max (tree-height (car x)) ;Recursive Case (tree-height (cdr x)))) ))

  6. Cases • Any working recursive function must have at least two cases: • Base Case: • Indicates when to stop • Smallest possible problem instance (empty list, zero, etc.) • Recursive Case: • Calls the function again, but on different arguments • Formally, the arguments in recursive calls must be “smaller” in some way (shorter list, closer to zero, etc.) • May have multiple base and/or recursive cases

  7. Example 2: Average (defun count (x) ; Same as LISP’s length function (if (atom x) 0 (1+ (count (cdr x))) )) (defun sum (x) (if (atom x) 0 (+ (car x) (sum (cdr x))) )) (defun average (x) (/ (sum x) (count x)))

  8. Tail Recursion • Tail recursive functions do no work after the recursive call. The function returns whatever the recursive call returns • Can be executed more efficiently by the LISP system • Often accomplished by introducing an extra accumulator parameter

  9. Example 3: Tail Recursive Average (defun count (x acc) (if (atom x) acc (count (cdr x) (1+ acc)) )) (defun sum (x acc) (if (atom x) acc (sum (cdr x) (+ (car x) acc)) )) (defun average (x) (/ (sum x 0) (count x 0)))

  10. Example 4: Single Pass Average • The last example still had to traverse the list twice: once for count and once for sum • Why not give average accumulators? (defun average-help (x count sum) (if (atom x) (/ sum count) (average-help (cdr x) (1+ count) (+ (car x) sum)) )) (defun average (x) (average-help x 0 0))

  11. Conclusion on Tail Recursion • Often need to introduce accumulator(s) and helper functions to hide accumulators from users • Not every recursive function can be rewritten using tail recursion • For example, tree-height has two recursive calls

  12. Trace • When debugging, it is often useful to trace calls of the recursive function (trace function-name) • Causes every call of the recursive function to be printed along with its call depth • Turn off using untrace (untrace function-name)

  13. Trace Example >(trace average-help) (AVERAGE-HELP) >(average '(5 1 30 4)) 1> (AVERAGE-HELP (5 1 30 4) 0 0) 2> (AVERAGE-HELP (1 30 4) 1 5) 3> (AVERAGE-HELP (30 4) 2 6) 4> (AVERAGE-HELP (4) 3 36) 5> (AVERAGE-HELP NIL 4 40) <5 (AVERAGE-HELP 10) <4 (AVERAGE-HELP 10) <3 (AVERAGE-HELP 10) <2 (AVERAGE-HELP 10) <1 (AVERAGE-HELP 10) 10 >(untrace average-help) (AVERAGE-HELP)

More Related