## Guards and Pattern Matching # Continued --- CS 135 // 2021-02-16 ## Administrivia - MathCS Special Interest Group + A Microsoft Team was created for cultivating a community for students interested in math and computing + Within this group, I am considering creating an informal, bi-weekly, discussion group on computing topics + If you're interested in joining, please reach out ## Administrivia - Am considering giving students the option of submitting on codePost individually + I'd pair students who want a partner together + And pair students who want to work individually + Individuals in the latter group could start the lab together but finish it and submit it individually - If such a policy were adopted, would you be interested in it? # Questions ## ...about anything? # Lab 2a Review # Tail Recursion ## Factorial, Revisited - Consider the following implementation of the `factorial` function ```haskell factorial :: Integer -> Integer factorial 0 = 1 factorial n = n * (factorial (n-1)) ``` ## Factorial, Revisited - When evaluating the `factorial` function, the following happens: ```text[1|2|3|4|5|6|7|8|9|10|11|1-11] factorial 5 ==> 5 * factorial 4 ==> 5 * (4 * factorial 3) ==> 5 * (4 * (3 * factorial 2)) ==> 5 * (4 * (3 * (2 * factorial 1))) ==> 5 * (4 * (3 * (2 * (1 * factorial 0)))) ==> 5 * (4 * (3 * (2 * (1 * 1)))) ==> 5 * (4 * (3 * (2 * 1))) ==> 5 * (4 * (3 * 2)) ==> 5 * (4 * 6) ==> 5 * 24 ==> 120 ``` - Notice how the expression gets arbitrarily large ## Factorial, Revisited - Consider the alternative implementation: ```haskell factorial :: Integer -> Integer factorial n = factorial' 1 n factorial' :: Integer -> Integer -> Integer factorial' total 0 = total factorial' total n = factorial' (total * n) (n-1) ``` ## Factorial, Revisited - When evaluating this `factorial` function, we get: ```text[1|2|3|4|5|6|7|1-7] factorial 5 ==> factorial' 1 5 ==> factorial' 5 4 ==> factorial' 20 3 ==> factorial' 60 2 ==> factorial' 120 1 ==> factorial' 120 0 ==> 120 ``` - Notice that the expression does not grow larger and larger since the answer is being accumulated through the parameter `total` ## Tail Calls - A **tail call** is when a procedure immediately returns the result of another procedure ```haskell factorial n = factorial' 1 n ``` ```haskell factorial' total n = factorial' (total * n) (n-1) ``` - Tail calls are implemented behind the scenes in **constant memory** since they do not need to use the call stack ## Tail Recursion - If a function only makes tail calls to itself, it is called **tail recursive** - Often tail recursive functions need to be implemented with a **helper function** that propagates information via a parameter ## Length of a List - Consider the following implementation of the `length` function: ```haskell length :: [a] -> Integer length [] = 0 length xs = 1 + length (tail xs) ``` - Is this tail recursive? + No, it is adding 1 to the result of calling `length` ## Length of a List - Can we implement it tail recursively? + Absolutely! We just need a helper function ```haskell length :: [a] -> Integer length xs = length' 0 xs length' :: Integer -> [a] -> Integer length' n [] = n length' n xs = length' (n+1) (tail xs) ``` ## Lab Time - You will be sent into a breakout session with your partner for this week - Start working on the `Lab2b.hs` exercises - The lab is due before class on Thursday + You only need to submit **once** on codePost and share the partner link with your partner