Definition of a Tail Recursive Function: ========================================= * A tail recursive function is a function which evaluates to an invocation of itself, NOT a function of an invocation of itself. Example: Non Tail Recursive: ------------------ fun sum(x) = if x > 0 0 then sum(x-1) + x else 0 Tail Recursive: ------------------ fun sum'(x,k) = if x > 0 then sum(x-1,k+x) else k fun sum(x) = sum'(x,0) * Why is tail recursion better? First example: ------------------ sum(5) => => sum(4) + 5 => sum(3) + 4 + 5 => sum(2) + 3 + 4 + 5 Takes up lots of space on the stack. Second Example: ---------------- sum(5) => => sum'(5,0) => sum'(4,5) => sum'(3,9) => sum'(2,12) => sum'(1,14) => sum'(0,15) => 15 Structural Induction =============================== Mathematical Induction - Dominoes Complete Induction - Pyramids Structural Induction - Electrical Power Strips Structural Induction is an induction over the STRUCTURE of a DATATYPE definition. // This is *very* close to the definition of lists: - datatype 'a list = nil | :: of ('a * 'a list); datatype 'a list = :: of 'a * 'a list | nil // not quite -- "op" and "infix" needed.... (:: is actually a function! Its type is ('a * 'a list) -> 'a list) Why does the first example here work but not the second?? - 1::2::3::4; stdIn:1.1-21.6 Error: operator and operand don't agree [literal] operator domain: int * int list operand: int * int in expression: 3 :: 4 - 1::2::3::4::nil; val it = [1,2,3,4] : int list fun reverse' (nil) rest = rest | reverse' (h::t) rest = reverse' t (h::rest) fun reverse mylist = reverse' mylist nil Induction: ---------- Base case: reverse' nil B => B Inductive case: For notational convenience, let rtail = the correct reversal of tail. Assume that (reverse' tail B) = rtail::B Prove that reverse' (head::tail) B = rtail::head::B reverse' (head::tail) B => reverse' tail (head::B) Let B' = head::B => reverse' tail B' => rtail::B' (by the assumption above) => rtail::head::B QED This is TAIL RECURSIVE! =) =)