CS 321 Programming Languages Forward Recursion Functions Calls
Total Page:16
File Type:pdf, Size:1020Kb
tally [] y0 tally [] y0 tally [8] y8+0 tally [8] y8+0 tally [6;8] y6+8 tally [6;8] y6+8 tally [2;6;8] y2+14 y2+14 y4+16 y4+16 20 20 Forward recursion CS 321 Programming Languages In forward recursion, you first call the function recursively on all Intro to OCaml – Recursion (tail vs forward) the recursive components, and then build the final result from the partial results. Baris Aktemur Wait until the whole structure has been traversed to start building Ozye˘ginUniversity¨ the answer. th # let rec tally lst= Last update made on Thursday 12 October, 2017 at 11:25. match lst with |[] ->0 |x::xs ->x+ tally xs;; Much of the contents here are taken from Elsa Gunter and Sam # let rec squareUp lst= Kamin’s OCaml notes available at match lst with http://courses.engr.illinois.edu/cs421 |[] ->[] |x::xs ->(x*x)::squareUp xs;; Ozye˘gin¨ University — CS 321 Programming Languages 1 Ozye˘gin¨ University — CS 321 Programming Languages 2 Functions calls and the stack Functions calls and the stack tally [2;6;8] tally [4;2;6;8] tally [4;2;6;8] Ozye˘gin¨ University — CS 321 Programming Languages 3 Ozye˘gin¨ University — CS 321 Programming Languages 3 tally [] y0 tally [] y0 tally [8] y8+0 y8+0 y6+8 y6+8 y2+14 y2+14 y4+16 y4+16 20 20 y0 y8+0 y8+0 y6+8 y6+8 y2+14 y2+14 y4+16 y4+16 20 20 Functions calls and the stack Functions calls and the stack tally [8] tally [6;8] tally [6;8] tally [2;6;8] tally [2;6;8] tally [4;2;6;8] tally [4;2;6;8] Ozye˘gin¨ University — CS 321 Programming Languages 3 Ozye˘gin¨ University — CS 321 Programming Languages 3 Functions calls and the stack Functions calls and the stack tally [] tally [] y0 tally [8] tally [8] tally [6;8] tally [6;8] tally [2;6;8] tally [2;6;8] tally [4;2;6;8] tally [4;2;6;8] Ozye˘gin¨ University — CS 321 Programming Languages 3 Ozye˘gin¨ University — CS 321 Programming Languages 3 tally [] y0 tally [] y0 tally [8] y8+0 y6+8 y2+14 y2+14 y4+16 y4+16 20 20 tally [] y0 tally [] y0 tally [8] y8+0 tally [8] y8+0 tally [6;8] y6+8 tally [6;8] y6+8 tally [2;6;8] y2+14 y4+16 20 20 Functions calls and the stack Functions calls and the stack tally [8] y8+0 tally [6;8] tally [6;8] y6+8 tally [2;6;8] tally [2;6;8] tally [4;2;6;8] tally [4;2;6;8] Ozye˘gin¨ University — CS 321 Programming Languages 3 Ozye˘gin¨ University — CS 321 Programming Languages 3 Functions calls and the stack Functions calls and the stack tally [2;6;8] y2+14 tally [4;2;6;8] tally [4;2;6;8] y4+16 Ozye˘gin¨ University — CS 321 Programming Languages 3 Ozye˘gin¨ University — CS 321 Programming Languages 3 tally [] y0 tally [8] y8+0 tally [6;8] y6+8 tally [2;6;8] y2+14 tally [4;2;6;8] y4+16 tally [] 20 y20 tally [] 20 y20 tally [8] 12 y20 tally [8] 12 y20 tally [6;8] 6 y20 tally [6;8] 6 y20 tally [2;6;8] 4 y20 y20 y20 y20 20 20 Functions calls and the stack Tail recursion A recursive function is tail-recursive if all recursive calls are the last thing that the function does. Tail recursion generally requires extra “accumulator” arguments to pass partial results. I May require an auxiliary function. # let rec tally lst acc= match lst with |[] -> acc 20 |x::xs -> tally xs(x+acc);; val tally:’a list -> int -> int # tally[1;2;3;4;5]0;; (* Have to give an initial accumulated value *) val it: int= 15 Ozye˘gin¨ University — CS 321 Programming Languages 3 Ozye˘gin¨ University — CS 321 Programming Languages 4 Functions calls and the stack Functions calls and the stack tally [2;6;8] 4 tally [4;2;6;8] 0 tally [4;2;6;8] 0 Ozye˘gin¨ University — CS 321 Programming Languages 5 Ozye˘gin¨ University — CS 321 Programming Languages 5 tally [] 20 y20 tally [] 20 y20 tally [8] 12 y20 y20 y20 y20 y20 y20 y20 y20 20 20 y20 y20 y20 y20 y20 y20 y20 y20 y20 20 20 Functions calls and the stack Functions calls and the stack tally [8] 12 tally [6;8] 6 tally [6;8] 6 tally [2;6;8] 4 tally [2;6;8] 4 tally [4;2;6;8] 0 tally [4;2;6;8] 0 Ozye˘gin¨ University — CS 321 Programming Languages 5 Ozye˘gin¨ University — CS 321 Programming Languages 5 Functions calls and the stack Functions calls and the stack tally [] 20 tally [] 20 y20 tally [8] 12 tally [8] 12 tally [6;8] 6 tally [6;8] 6 tally [2;6;8] 4 tally [2;6;8] 4 tally [4;2;6;8] 0 tally [4;2;6;8] 0 Ozye˘gin¨ University — CS 321 Programming Languages 5 Ozye˘gin¨ University — CS 321 Programming Languages 5 tally [] 20 y20 tally [] 20 y20 tally [8] 12 y20 y20 y20 y20 y20 y20 20 20 tally [] 20 y20 tally [] 20 y20 tally [8] 12 y20 tally [8] 12 y20 tally [6;8] 6 y20 tally [6;8] 6 y20 tally [2;6;8] 4 y20 y20 20 20 Functions calls and the stack Functions calls and the stack tally [8] 12 y20 tally [6;8] 6 tally [6;8] 6 y20 tally [2;6;8] 4 tally [2;6;8] 4 tally [4;2;6;8] 0 tally [4;2;6;8] 0 Ozye˘gin¨ University — CS 321 Programming Languages 5 Ozye˘gin¨ University — CS 321 Programming Languages 5 Functions calls and the stack Functions calls and the stack tally [2;6;8] 4 y20 tally [4;2;6;8] 0 tally [4;2;6;8] 0 y20 Ozye˘gin¨ University — CS 321 Programming Languages 5 Ozye˘gin¨ University — CS 321 Programming Languages 5 tally [] 20 y20 tally [8] 12 y20 tally [6;8] 6 y20 tally [2;6;8] 4 y20 tally [4;2;6;8] 0 y20 Functions calls and the stack An optimization idea Observation When we have tail recursion, a function that is waiting for the called function to return a value simply propagates the return value to its caller. Idea We don’t need to keep the frame of a tail-recursive function on the 20 stack. Simply replace the tail-recursive function’s stack frame with the called function. Ozye˘gin¨ University — CS 321 Programming Languages 5 Ozye˘ginUniversity¨ — CS 321 Programming Languages 6 Functions calls and the stack Functions calls and the stack tally [4;2;6;8] 0 tally [2;6;8] 4 Ozye˘gin¨ University — CS 321 Programming Languages 7 Ozye˘gin¨ University — CS 321 Programming Languages 8 y20 Functions calls and the stack Functions calls and the stack tally [6;8] 6 tally [8] 12 Ozye˘gin¨ University — CS 321 Programming Languages 9 Ozye˘ginUniversity¨ — CS 321 Programming Languages 10 Functions calls and the stack Functions calls and the stack tally [] 20 tally [] 20 y20 Ozye˘ginUniversity¨ — CS 321 Programming Languages 11 Ozye˘ginUniversity¨ — CS 321 Programming Languages 11 ifn=0 then[] elsex:: makeList x(n-1);; Functions calls and the stack Why do we care? Reusing the stack frame of the tail-recursive function is known as 20 the tail call optimization. It is an automatic optimization applied by the compilers and interpreters. Ozye˘ginUniversity¨ — CS 321 Programming Languages 12 Ozye˘ginUniversity¨ — CS 321 Programming Languages 13 Experiment Experiment Write a function that takes a value x and an integer n, and returns Write a function that takes a value x and an integer n, and returns a list of length n whose elements are all x. a list of length n whose elements are all x. # let rec makeList x n= # let rec makeList x n= ifn=0 then[] elsex:: makeList x(n-1);; val makeList:’a -> int ->’a list=<fun> val makeList:’a -> int ->’a list=<fun> # makeList "a"5;; # makeList "a"5;; -: string list=["a"; "a"; "a"; "a"; "a"] -: string list=["a"; "a"; "a"; "a"; "a"] # makeList3 40;; # makeList3 40;; -: int list= -: int list= [3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; [3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; 3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; 3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; 3;3;3;3;3;3;3;3;3;3] 3;3;3;3;3;3;3;3;3;3] Ozye˘ginUniversity¨ — CS 321 Programming Languages 14 Ozye˘ginUniversity¨ — CS 321 Programming Languages 14 Experiment Experiment # let rec makeList x n acc= ifn=0 then acc else makeList x(n-1)(x::acc);; # makeList3 99999;; -: int list= val makeList:’a -> int ->’a list ->’a list=<fun> [3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; 3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; # makeList3 10[];; 3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; -: int list=[3;3;3;3;3;3;3;3;3;3] 3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; ...] # makeList3 12345678[];; # makeList3 1234567;; -: int list= [3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3;3; Stack overflow during evaluation (looping recursion?).