title: CS450 layout: true author: Tiago Cogumbreiro lecture: 08 abstract: foldl, looping last-to-first; tail-recursion sep: ☽ <img id="logo" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iYSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMTI0LjggNTkuNiI+PGRlZnM+PHN0eWxlPi5ie2ZpbGw6IzAwNWE4Yjt9PC9zdHlsZT48L2RlZnM+PHBhdGggY2xhc3M9ImIiIGQ9Ik02LjQ1LDQzLjkxYzEuMzgsMCwyLjUyLS4zMiwzLjQtLjk3LC44OC0uNjUsMS4zMi0xLjUyLDEuMzItMi42MSwwLS43OC0uMjctMS40Ny0uODEtMi4wNS0uNTQtLjU4LTEuMjUtLjk1LTIuMTUtMS4wOSwxLjY5LS41MSwyLjUzLTEuNTIsMi41My0zLjAzLDAtLjk1LS4zNy0xLjcxLTEuMTItMi4yNy0uNzUtLjU2LTEuODEtLjg0LTMuMTktLjg0SC4yOHYxMi44NUg2LjQ1Wm0tMy4zOC0xMC41NGgyLjk0Yy42NSwwLDEuMTQsLjExLDEuNDYsLjMyLC4zMiwuMjEsLjQ5LC41NywuNDksMS4wNiwwLC45My0uNjUsMS40LTEuOTUsMS40SDMuMDd2LTIuNzdoMFptMCw1LjAxaDIuOTdjMS40OSwwLDIuMjQsLjU0LDIuMjQsMS42MnMtLjc1LDEuNi0yLjI0LDEuNkgzLjA3di0zLjIxaDBabTEwLjcsNC40M2MuOTIsLjkyLDIuMDcsMS4zOSwzLjQ1LDEuMzlzMi41OS0uNDUsMy40OS0xLjM0Yy44OS0uODksMS4zNC0yLjA3LDEuMzQtMy41NHMtLjQ1LTIuNjItMS4zNS0zLjUyYy0uOS0uOS0yLjA2LTEuMzUtMy40OC0xLjM1cy0yLjU2LC40NS0zLjQ3LDEuMzVjLS45MSwuOS0xLjM2LDIuMDctMS4zNiwzLjUycy40NiwyLjU3LDEuMzgsMy41aDBabTMuNDUtLjY5Yy0uNjYsMC0xLjE4LS4yNC0xLjU1LS43MS0uMzctLjQ3LS41Ni0xLjE2LS41Ni0yLjA3cy4xOS0xLjYxLC41Ni0yLjFjLjM3LS41LC44OS0uNzQsMS41NS0uNzRzMS4xOCwuMjUsMS41NSwuNzRjLjM3LC41LC41NiwxLjIsLjU2LDIuMXMtLjE5LDEuNTktLjU2LDIuMDdjLS4zNywuNDctLjg5LC43MS0xLjU1LC43MWgwWm03LjI2LDEuMzJjLjgsLjQ4LDEuNzUsLjcyLDIuODQsLjcyLDEuMzIsMCwyLjM2LS4yNywzLjEyLS44MiwuNzYtLjU0LDEuMTQtMS4yOCwxLjE0LTIuMjEsMC0xLjUxLTEuMDUtMi40Ni0zLjE2LTIuODZsLTEuMjctLjI0Yy0uNDktLjA5LS44Mi0uMTktMS0uMzItLjE4LS4xMy0uMjctLjMyLS4yNy0uNThzLjExLS40OCwuMzQtLjY0Yy4yMy0uMTYsLjU1LS4yNCwuOTYtLjI0LC45MiwwLDEuNTQsLjQzLDEuODUsMS4yOWwyLjE1LS45N2MtLjI1LS41OC0uNy0xLjA3LTEuMzctMS40OS0uNjctLjQyLTEuNS0uNjItMi41MS0uNjItMS4yMSwwLTIuMTcsLjI2LTIuODgsLjc5LS43MSwuNTMtMS4wNiwxLjIzLTEuMDYsMi4xMXMuMjQsMS40OCwuNzMsMS44OWMuNDgsLjQyLDEuMjYsLjczLDIuMzIsLjk0bDEuMywuMjZjLjQyLC4wOSwuNzEsLjIxLC44OCwuMzYsLjE3LC4xNSwuMjYsLjM2LC4yNiwuNjJzLS4xMywuNDktLjM4LC42NmMtLjI1LC4xNy0uNTksLjI2LTEuMDIsLjI2LS43NywwLTEuMjktLjE3LTEuNTYtLjUxLS4yOC0uMzYtLjQ2LS43LS41My0xLjAzbC0yLjM3LC43NWMuMTgsLjgsLjY4LDEuNDMsMS40OCwxLjkxaDBabTkuOTgtLjJjLjQyLC40NCwuOTksLjY2LDEuNzEsLjY2aDMuMDd2LTIuMDdoLTEuOThjLS4yOCwwLS40OS0uMDYtLjYyLS4xOS0uMTMtLjEzLS4xOS0uMzMtLjE5LS42MnYtNC4zMWgyLjM5di0xLjk4aC0yLjM5di0yLjg4aC0yLjYxdjIuODhoLTEuOTN2MS45OGgxLjkzdjQuNzljMCwuNzIsLjIxLDEuMywuNjIsMS43NGgwWm02Ljc2LS40M2MuOTIsLjkyLDIuMDcsMS4zOSwzLjQ1LDEuMzlzMi41OS0uNDUsMy40OS0xLjM0Yy44OS0uODksMS4zNC0yLjA3LDEuMzQtMy41NHMtLjQ1LTIuNjItMS4zNS0zLjUyYy0uOS0uOS0yLjA2LTEuMzUtMy40OC0xLjM1cy0yLjU2LC40NS0zLjQ3LDEuMzVjLS45MSwuOS0xLjM2LDIuMDctMS4zNiwzLjUycy40NiwyLjU3LDEuMzgsMy41aDBabTMuNDUtLjY5Yy0uNjYsMC0xLjE4LS4yNC0xLjU1LS43MS0uMzctLjQ3LS41Ni0xLjE2LS41Ni0yLjA3cy4xOS0xLjYxLC41Ni0yLjFjLjM3LS41LC44OS0uNzQsMS41NS0uNzRzMS4xOCwuMjUsMS41NSwuNzRjLjM3LC41LC41NiwxLjIsLjU2LDIuMXMtLjE5LDEuNTktLjU2LDIuMDdjLS4zNywuNDctLjg5LC43MS0xLjU1LC43MWgwWm05LjE2LDEuNzh2LTQuMzVjMC0xLjE1LC4yLTEuOTcsLjYxLTIuNDYsLjI3LS4zMywuNjgtLjUsMS4yMy0uNSwuOTgsMCwxLjQ3LC41OCwxLjQ3LDEuNzN2NS41OGgyLjYxdi02LjE1YzAtMS4wNS0uMjUtMS44Ny0uNzYtMi40NC0uNTEtLjU4LTEuMjYtLjg2LTIuMjctLjg2LTEuMjgsMC0yLjI3LC41Ni0yLjk2LDEuNjl2LTEuNDFoLTIuNTN2OS4xOGgyLjYxWiIvPjxwYXRoIGNsYXNzPSJiIiBkPSJNMS44NiwyNS43YzEuMDUsLjk1LDIuNDQsMS40Myw0LjE5LDEuNDNzMy4xLS40OCw0LjE3LTEuNDNjMS4wNi0uOTUsMS42LTIuMjUsMS42LTMuODd2LTcuODRoLTIuNzl2Ny40YzAsMi4yNC0uOTksMy4zNi0yLjk3LDMuMzYtLjk4LDAtMS43Mi0uMjgtMi4yMi0uODUtLjUtLjU3LS43NS0xLjQtLjc1LTIuNTF2LTcuNEguMjl2Ny44NGMwLDEuNjMsLjUyLDIuOTIsMS41NywzLjg3aDBabTE1LjUsMS4xNHYtMTAuNDZsMy41NCwxMC40NmgyLjQ4bDMuNTgtMTAuNDh2MTAuNDhoMi43OVYxMy45OWgtNC40MWwtMi4xNSw2LjI2Yy0uNCwxLjIxLS43MywyLjEyLS45NywyLjc0LS4yNC0uNjEtLjU3LTEuNTItLjk3LTIuNzRsLTIuMTEtNi4yNmgtNC41N3YxMi44NWgyLjc5Wm0xNS4xMy0uNDRjLjU1LC40OSwxLjI0LC43MywyLjA3LC43MywxLjM4LDAsMi40My0uNTQsMy4xNC0xLjYzLC4xLC44OSwuNjUsMS4zNCwxLjY1LDEuMzRoMnYtMS45OGgtLjgxYy0uMjUsMC0uNC0uMDMtLjQ2LS4wOS0uMDYtLjA2LS4wOS0uMjEtLjA5LS40NnYtMy4zNmMwLTEuMTctLjM1LTIuMDYtMS4wNi0yLjY2LS43LS42LTEuNzItLjktMy4wNC0uOS0xLjI1LDAtMi4yNywuMjgtMy4wNiwuODMtLjc5LC41NS0xLjIyLDEuMjEtMS4yOSwxLjk4bDIuMzUsLjUxYy4yMy0uOTcsLjkxLTEuNDUsMi4wMi0xLjQ1LDEsMCwxLjUxLC40MiwxLjUxLDEuMjd2LjM1Yy0uODksLjA5LTEuNjcsLjIxLTIuMzIsLjM2LS42NSwuMTUtMS4yNSwuMzYtMS43OCwuNjMtLjUzLC4yNy0uOTQsLjYyLTEuMjIsMS4wNi0uMjgsLjQ0LS40MywuOTYtLjQ0LDEuNTYsMCwuNzgsLjI4LDEuNDIsLjgzLDEuOTFoMFptNC4zOS0xLjczYy0uMzcsLjM3LS44MywuNTUtMS4zOCwuNTUtLjgsMC0xLjE5LS4zMy0xLjE5LS45OSwwLS41NCwuMjYtLjkzLC43Ny0xLjE3LC41MS0uMjQsMS4zLS40MywyLjM1LS41N3YuNTljMCwuNy0uMTgsMS4yMy0uNTUsMS42aDBabTYuMzgsMS43MWMuOCwuNDgsMS43NSwuNzIsMi44NCwuNzIsMS4zMiwwLDIuMzYtLjI3LDMuMTItLjgyLC43Ni0uNTQsMS4xNC0xLjI4LDEuMTQtMi4yMSwwLTEuNTEtMS4wNS0yLjQ2LTMuMTYtMi44NmwtMS4yNy0uMjRjLS40OS0uMDktLjgyLS4xOS0xLS4zMi0uMTgtLjEzLS4yNy0uMzItLjI3LS41OHMuMTEtLjQ4LC4zNC0uNjRjLjIzLS4xNiwuNTUtLjI0LC45Ni0uMjQsLjkyLDAsMS41NCwuNDMsMS44NSwxLjI5bDIuMTUtLjk3Yy0uMjQtLjU4LS43LTEuMDctMS4zNy0xLjQ5LS42Ny0uNDItMS41LS42Mi0yLjUxLS42Mi0xLjIxLDAtMi4xNywuMjYtMi44OCwuNzktLjcxLC41My0xLjA3LDEuMjMtMS4wNywyLjExcy4yNCwxLjQ3LC43MiwxLjg5Yy40OCwuNDIsMS4yNiwuNzMsMi4zMiwuOTRsMS4zLC4yNmMuNDIsLjA5LC43MSwuMjEsLjg4LC4zNiwuMTcsLjE1LC4yNiwuMzYsLjI2LC42MnMtLjEzLC40OS0uMzgsLjY2Yy0uMjUsLjE3LS41OSwuMjYtMS4wMiwuMjYtLjc3LDAtMS4yOS0uMTctMS41Ni0uNTEtLjI4LS4zNS0uNDYtLjctLjUzLTEuMDNsLTIuMzcsLjc1Yy4xOCwuOCwuNjgsMS40MywxLjQ4LDEuOTFoMFptOS40NSwwYy44LC40OCwxLjc1LC43MiwyLjg0LC43MiwxLjMyLDAsMi4zNi0uMjcsMy4xMi0uODIsLjc2LS41NCwxLjE0LTEuMjgsMS4xNC0yLjIxLDAtMS41MS0xLjA1LTIuNDYtMy4xNi0yLjg2bC0xLjI3LS4yNGMtLjQ5LS4wOS0uODItLjE5LTEtLjMyLS4xOC0uMTMtLjI3LS4zMi0uMjctLjU4cy4xMS0uNDgsLjM0LS42NGMuMjMtLjE2LC41NS0uMjQsLjk2LS4yNCwuOTIsMCwxLjU0LC40MywxLjg1LDEuMjlsMi4xNS0uOTdjLS4yNC0uNTgtLjctMS4wNy0xLjM3LTEuNDktLjY3LS40Mi0xLjUtLjYyLTIuNTEtLjYyLTEuMjEsMC0yLjE3LC4yNi0yLjg4LC43OS0uNzEsLjUzLTEuMDcsMS4yMy0xLjA3LDIuMTFzLjI0LDEuNDcsLjczLDEuODljLjQ4LC40MiwxLjI2LC43MywyLjMyLC45NGwxLjMsLjI2Yy40MiwuMDksLjcxLC4yMSwuODgsLjM2LC4xNywuMTUsLjI2LC4zNiwuMjYsLjYycy0uMTMsLjQ5LS4zOCwuNjZjLS4yNSwuMTctLjU5LC4yNi0xLjAyLC4yNi0uNzcsMC0xLjI5LS4xNy0xLjU2LS41MS0uMjgtLjM1LS40Ni0uNy0uNTMtMS4wM2wtMi4zNywuNzVjLjE4LC44LC42OCwxLjQzLDEuNDgsMS45MWgwWiIvPjxwYXRoIGNsYXNzPSJiIiBkPSJNMTIzLjU2LDM3Ljk1YzAtNS40NCwwLTEwLjg5LDAtMTYuMzMsMC0uNTMtLjAyLTEuMDYtLjA0LTEuNi0uMDUtMS4xNS0uMjItMi4yOS0uNDctMy40MS0xLjY2LTcuNDEtNy4yMy0xMy4zNi0xNC41LTE1LjUtMS42Ni0uNDktMy4zNi0uNzgtNS4xLS44Mi0uNTQtLjAxLTEuMDgsMC0xLjYyLDBoLTM2LjU2di40YzAsNy4xOCwwLDE0LjM2LDAsMjEuNTQsMCw1LjI1LDAsMTAuNTEsMCwxNS43NiwwLC42NiwuMDQsMS4zMywuMDgsMS45OSwuMDksMS4zMiwuMzQsMi42MSwuNjksMy44OCwxLjc4LDYuNDYsNi43MSwxMS43OCwxMywxNC4wNiwyLjM4LC44Niw0LjgzLDEuMjYsNy4zNiwxLjI2LDUuMiwwLDEwLjQsMCwxNS42LDAsLjg0LDAsMS42Ny0uMDQsMi41MS0uMDksMS4wNC0uMDYsMi4wNi0uMjQsMy4wNy0uNDksNS4yMi0xLjMyLDkuMzUtNC4yMSwxMi4zOS04LjY0LDEuNjgtMi40NCwyLjc0LTUuMTQsMy4yNy04LjA2LC4yMy0xLjMsLjMyLTIuNjEsLjMyLTMuOTNoMFptLTIwLjAxLTIzLjc5Yy0uMDMsLjg3LS4xMiwxLjcyLS4zNCwyLjU2LS4zLDEuMTktLjgzLDIuMjYtMS42OCwzLjE1LS42OCwuNzItMS41LDEuMjQtMi40MSwxLjYzLTEuMDcsLjQ2LTIuMTksLjczLTMuMzUsLjg5LTEuMjYsLjE4LTIuNTMsLjIyLTMuODEsLjIxLS42MywwLTEuMjYsMC0xLjg4LDBoLS4zMVY4LjE5YzAtLjYzLC4wMS0xLjI2LC4xMS0xLjg4LC4wMi0uMTEsLjA0LS4yMiwuMDYtLjMzLC4wOC0uNDQsLjMzLS43MiwuNzgtLjg1LC41NS0uMTYsMS4xMi0uMjksMS42OS0uMzQsLjY3LS4wNiwxLjM0LS4xLDIuMDEtLjEsMS4zMiwwLDIuNjIsLjE4LDMuODgsLjY0LDIuNDQsLjg4LDQuMDMsMi41OCw0Ljc5LDUuMDYsLjM4LDEuMjMsLjUsMi40OSwuNDUsMy43N2gwWm0yLjM5LDIwLjQ4Yy4zMiwxLjMyLC40MSwyLjY3LC4zMyw0LjAyLS4wNiwxLjExLS4yNCwyLjItLjYxLDMuMjUtLjg3LDIuNDgtMi41NSw0LjItNC45NCw1LjI1LTEuMDEsLjQ0LTIuMDcsLjczLTMuMTYsLjg5LS45NCwuMTUtMS44OSwuMjItMi44NCwuMTktLjg3LS4wMy0xLjc0LS4wOS0yLjU4LS4zNS0uOTQtLjI5LTEuNTctLjktMS45LTEuODMtLjIzLS42Ni0uMzUtMS4zNS0uNC0yLjA1LS4wNC0uNy0uMDctMS4zOS0uMDctMi4wOSwwLTQuNzUsMC05LjQ5LDAtMTQuMjR2LS40Yy4xMiwwLC4yMS0uMDEsLjI5LS4wMSwxLjEyLDAsMi4yMy0uMDEsMy4zNSwuMDEsMi4wMiwuMDUsNC4wMSwuMjksNS45NSwuODgsLjk5LC4zLDEuOTMsLjcsMi44MSwxLjI1LDEuOTcsMS4yMiwzLjIsMi45NywzLjc1LDUuMjFoMFptMTUuNjQsMy43OWMtLjA0LDQuODQtMS43NCw5LjA3LTUuMDEsMTIuNjQtMi41NywyLjgxLTUuNzIsNC42Ny05LjQyLDUuNThoMGMtLjkxLC4yMy0xLjg0LC40LTIuNzgsLjQ1LS43MSwuMDQtMS40MywuMDktMi4xNCwuMDktNS4zNSwwLTEwLjcsLjAxLTE2LjA1LDAtMy43OCwwLTcuMjYtMS4wNS0xMC40MS0zLjEzLTEuNjgtMS4xMS0zLjE0LTIuNDYtNC40LTQuMDQtMS4wMy0xLjI5LTEuNjMtMi43Ny0xLjg5LTQuNC0uMTgtMS4xMy0uMjItMi4yNi0uMTItMy4zOSwuMS0xLjE2LC4yNC0yLjMyLC4zNi0zLjQ5LC4xMi0xLjExLC4yNS0yLjIyLC4zOS0zLjMzLC4xMy0xLjEsLjI2LTIuMiwuMzktMy4zLC4xMS0uOTYsLjIyLTEuOTIsLjM0LTIuODgsLjExLS45NSwuMjMtMS45LC4zNC0yLjg2LC4xMS0uOTYsLjIzLTEuOTIsLjM0LTIuODgsLjExLS45NSwuMjMtMS45LC4zNC0yLjg2LC4wOC0uNjUsLjE1LTEuMywuMjQtMS45NSwuMDMtLjE5LS4wMy0uMzItLjE4LS40NC0uMzgtLjMtLjc1LS42My0xLjEzLS45My0uMTItLjA5LS4xOC0uMi0uMTgtLjM1LDAtLjg5LDAtMi42NywwLTIuNjd2LS4yN2gyLjQ1di00LjZoLTEuMnMyLjc4LTIuMTcsNC4wOC0zLjE0Yy4xMy0uMSwuMjktLjM0LC4yOS0uNTQtLjAxLS44LDAtMS41NiwwLTIuMzYsMC0uMDgsMC0uMTYsMC0uMjQsLjAyLS4xMSwuMDgtLjE5LC4xOC0uMjIsLjAzLS4wMSwuMDYtLjAyLC4xLS4wMiwuMTQsMCwuMjUsLjA5LC4yNywuMjMsLjAxLC4wOCwwLC4xNiwwLC4yMywwLC44MiwuMDIsMS41NCwwLDIuMzYsMCwuMiwuMTQsLjQ0LC4yNywuNTQsMS4yOSwuOTYsNC4xMSwzLjE0LDQuMTEsMy4xNGgtMS4ydjQuNmgyLjQ2czAsLjI5LDAsLjY5YzAsLjU4LDAsMS42MiwwLDIuMjQsMCwuMTQtLjA1LC4yNC0uMTYsLjM0LS40MSwuMzMtLjgsLjY3LTEuMjEsMS0uMTIsLjA5LS4xNiwuMTktLjE0LC4zNCwuMSwuODcsLjE5LDEuNzMsLjI5LDIuNiwuMSwuODgsLjE5LDEuNzUsLjI4LDIuNjMsLjEsLjg5LC4yLDEuNzksLjI5LDIuNjgsLjA5LC44OCwuMTksMS43NSwuMjgsMi42MywuMSwuODksLjE5LDEuNzksLjI5LDIuNjgsLjEsLjg4LC4xOSwxLjc1LC4yOCwyLjYzLC4xLC45LC4yLDEuOCwuMjksMi43LC4wOSwuODgsLjE5LDEuNzUsLjI4LDIuNjMsLjEsLjg5LC4xOSwxLjc5LC4yOSwyLjY4LC4wOSwuODgsLjE5LDEuNzUsLjI4LDIuNjMsLjEyLDEuMTMsLjE5LDIuMjgsLjQ3LDMuMzksLjA5LC4zNSwuMTksLjcxLC4zMiwxLjA1LC41LDEuMzUsMS40NCwyLjI2LDIuNzgsMi43NiwuNzQsLjI3LDEuNTEsLjQzLDIuMjksLjUyLDEuMTksLjEzLDIuMzgsLjIsMy41OCwuMTUsMS4yNi0uMDUsMi41My0uMSwzLjc5LS4yLDEuODgtLjE2LDMuNzMtLjQ1LDUuNTUtLjkyLC42MS0uMTYsMS4yMS0uMzMsMS44MS0uNTMsMi4xMS0uNyw0LjA4LTEuNjYsNS44Ni0zLDEuOTItMS40NCwzLjQ4LTMuMTksNC41NC01LjM2LC42OC0xLjQxLDEuMDktMi45LDEuMjUtNC40NiwuMi0xLjk3LC4wNC0zLjktLjYtNS43OC0uNzYtMi4yMi0yLjEyLTQtMy45OS01LjQyLTEuNDgtMS4xMi0zLjEyLTEuOTEtNC44Ni0yLjUtLjQ5LS4xNy0xLS4zMS0xLjUtLjQ3LS4wOC0uMDMtLjE2LS4wNS0uMzEtLjA5LC4xMy0uMDcsLjIxLS4xMSwuMjktLjE1LDEuMTctLjU1LDIuMjgtMS4yMSwzLjI5LTIuMDIsMi4zMS0xLjg0LDMuOC00LjE5LDQuMjgtNy4xMiwuNTItMy4xMywuMDMtNi4xLTEuNjItOC44NC0uMS0uMTYtLjIyLS4zNC0uMzYtLjUzLS44My0xLjA2LTIuMjYtMi4zOS0yLjMtMi40NiwuMDgsLjAyLC4xNiwuMDQsLjI0LC4wNyw1LjQxLDEuODksOS4yNiw1LjQ3LDExLjU0LDEwLjczLC42NiwxLjUzLDEuMDgsMy4xMywxLjI5LDQuNzgsLjEsLjc3LC4xNiwxLjU1LC4xNiwyLjMyLC4wMSw1LjgsLjA1LDExLjYxLDAsMTcuNDFoMFpNNzUsMTQuMDRzMS45OCwwLDIuOTgsMGMwLTEuNTUsMC00LjYxLDAtNC42MWgtMi45OHY0LjZoMFptNDIuNDEsNDUuMTR2LTIuNTRoLjk1di0uMzRoLTIuMjh2LjM0aC45NXYyLjU0aC4zOFptMS43LDB2LTIuNDVsLjgzLDIuNDVoLjM0bC44NC0yLjQxdjIuNDFoLjM3di0yLjg4aC0uNTFsLS42OSwyYy0uMDcsLjItLjEyLC4zNi0uMTUsLjQ2LS4wMy0uMDktLjA3LS4yNC0uMTQtLjQzbC0uNjgtMi4wNGgtLjU3djIuODhoLjM3WiIvPjwvc3ZnPg==" height="64" /> .bottom-bar[ {{title}} {{sep}} {{abstract}} {{sep}} Lecture {{lecture}} {{sep}} {{author}} ] --- class: middle, full # {{title}} ## Structure of Higher Level Languages ### Lecture {{lecture}}: {{abstract}} ### {{author}} --- class: impact # Looping from last-to-first --- class: full, center, middle # Reversing a list --- # Exercise: write copy in terms of foldr .col-6[ ### Using our recursion pattern ```scheme (define (copy l) (match `l` ; (list 1 2 3) [(list) `(list)`] [(list h l ...) ; h = 1 ; l = (list 2 3) (define result (copy l)) ; result = (list 2 3) `(cons h result)` ; output = (list 1 2 3) ] )) ``` ] -- .col-6[ ### Using foldr ```scheme (define (copy-foldr l) (foldr ; step (lambda (h result) `(cons h result)` ) ; base-case `(list)` ; list we are iterating over `l` ) ) ``` ] --- # Reversing a list ## Aka copy in reverse .col-6[ ```scheme (define (reverse-copy l) (`foldr` ; step (lambda (h result) (cons h result) ) ; base-case (list) ; list we are iterating over l ) ) ``` ] .col-6[ - The difference between `foldr` and `foldl` is the traversal order - Copying is traversing last-to-first (since `cons` adds to the l-h-s) - Reversing is traversing first-to-last (first becomes last with `cons`) ] --- # Reversing ## Adding to the right-hand-side ```scheme (define (cons-right x l) ... ) ; x = 4 ; l = (list 1 2 3) ; output = (list 1 2 3 4) ``` --- # Reversing ## Adding to the right-hand-side .col-6[ ```scheme (define (cons-right x l) ; x = 4 ; l = (list 1 2 3) (match l [(list) (list x)] [(list h l ...) ; h = 1 ; l = (list 2 3) (define result (cons-right x l)) ; result = (list 2 3 4) (cons h result) ; output = (list 1 2 3 4) ] )) ``` ] .col-6[ ```scheme (define (reverse-slow l) (match l ; (list 1 2 3) [(list) (list)] [(list h l ...) ; h = 1 ; l = (list 2 3) (define result (reverse-slow l)) ; result = (list 3 2) (cons-right h result) ] ) ) ``` ] --- # Reversing ## Adding to the right-hand-side - The problem with `cons-right` is that it needs to traverse the whole list - Reversing effectively traverses the list $`\sum_{i \le n} i = \frac{(n - 1)n}{2}`$ times, thus makes a linear-time operation into quadratic! - <b>Can you implement `cons-right` and `reverse-slow` with either foldl or with foldr?</b> --- # Reversing a list Implement function `(reverse l)` that reverses a list. ### Spec ```scheme (check-equal? (list 4 3 2 1) (reverse (list 1 2 3 4))) ``` -- .col-6[ ### Solution .small[ ```scheme (define (reverse l) (define (rev accum l) (match l [(list) accum] [(list h l ...) (rev (cons h accum) l)])) (rev l (list))) ``` ] ] .col-6[ - We use a parameter `accum` as a "loop variable", that is, a variable that we update at each iteration. - The idea behind `rev` is that recursing can be thought of as "calling" the next iteration of the loop where we update the loop variables (ie, `accum` and `l` with their new respective values) ] --- class: full, center, middle # Joining strings in Racket --- # Joining strings in Python ```python >>> " + ".join(["x", "y", "z"]) "x + y + z" >>> " + ".join([]) "" >>> " + ".join(["x"]) "x" ``` --- # Joining strings in Racket ```scheme (require rackunit) (check-equal? (join ", " '("x" "y" "z")) "x, y, z") (check-equal? (join ", " '()) "") (check-equal? (join ", " '("x")) "x") ``` --- # Joining strings in Racket <div class="col-6" markdown> * **Separator as a suffix:**<br/> -- "x, y, z, " -- * **Separator as a suffix, but not on last:**<br/> -- "x, y, " + "z"<br/> .alt[How do you check the last?] -- * **Separator as a prefix:**<br/> -- ", x, y, z" -- * **Separator as a prefix, but not on first:**<br/> -- "x" + ", y, z" <br/> </div> --- # Separator as suffix .col-6.small[ ```scheme (define (join-suffix sep l) (match l [(list) ""] [(list x) x] [(list h l ...) (string-append h sep (join-suffix sep l)) ] ) ) ``` ] .col-6[ - We can use pattern `(list x)` to identify the *last element* - When we reach the last-element, we do not add a suffix - Otherwise, (third pattern) we suffix the element with the separator. - **Insight:** recursion+pattern matching lets us easily mention the last $k$ elements. - A problem of this solution is that it is less trivial to adapt it to `fold`s. ] --- # Separator as a prefix .col-6[ ```scheme (define (join-prefix sep l) (match l [(list) ""] [(list h l ...) (define (join-iter l) (match l [(list) ""] [(list h l ...) ; h = "b" ; l = (list "c") (string-append sep h (join-iter l)) ; output = ", b, c" ] ) ) (string-append h (join-iter l))])) ``` ] .col-6[ - If the list is empty, there is no separator to handle. - If the list is non-empty, we handle the first element differently, the rest of the list is handled recursively. - Recursively, traverse last-to-first, so add the separator as a prefix, in-order - **Try implementing `join-iter` with foldr!** ] --- # Separator as prefix <div class="col-6" markdown> ```scheme (define (join sep l) (define (join-iter accum l) (match l [(list) accum] [(list h l ...) (join-iter (string-append accum sep h) l)])) (match l [(list) ""] [(list h l ...) (join-iter h l)])) ``` </div> .col-6[ - This solution uses a parameter `accum` to build the list, rather than handling the result of recursion - This solution is more complicated, but faster (next lecture) ] --- # Imperative versus functional <div markdown class="col-6"> ```py def join(sep, l): if l == []: return "" accum = l[0] l = l[1:] for x in l: accum = accum + sep + x return accum >>> l = ["x", "y", "z"] >>> join(", ", l) 'x, y, z' ``` </div> <div markdown class="col-6"> ```scheme (define (join sep l) (define (join-iter accum l) (match l [(list) accum] [(list h l ...) (join-iter (string-append accum sep h) l)])) (match l [(list) ""] [(list h l ...) (join-iter h l)])) ``` </div> --- # Another pattern arises .col-6.small[ ```scheme ; Example 1 (define (reverse l) * (define (rev accum l) * (match l * [(list) accum] * [(list h l ...) (rev (cons h accum) l)])) (rev l (list))) ; Example 2 (define (join sep l) * (define (join-iter accum l) * (match l * [(list) accum] * [(list h l ...) * (join-iter * (string-append accum sep h) * l)])) (match l [(list) ""] [(list h l ...) (join-iter h l)])) ``` ] .col-6[ ### A generalized recursion pattern for lists ```scheme (define (rec base-case l) (match l [(list) base-case] [(list h l ...) (rec (step h accum) l)])) ``` #### For instance, ```scheme (cons h accum) ``` #### maps to ```scheme (step h accum) ``` ] --- # Implementing this recursion pattern .col-6[ ### Recursive pattern for lists ```scheme (define (rec base-case l) (match l [(list) base-case] [(list h l ...) (rec (step h accum) l)])) ``` ] .col-6[ ### Fold left reduction ```scheme (define (foldl step base-case l) (match l [(list) base-case] [(list h l ...) (foldl (step h accum) l)])) ``` ] --- # Implementing join with foldl <div class="col-5 small" markdown> ### Before ```scheme (define (join sep l) (define (join-iter accum l) (match l [(list) accum] [(list h l ...) (join-iter (string-append accum sep h) l)])) (match l [(list) ""] [(list h l ...) (join-iter h l)])) ``` </div> -- <div class="col-6" markdown> ### After ```scheme (define (join sep l) (match l [(list) ""] [(list h l ...) * (define (step elem accum) * (string-append accum sep elem)) * (foldl step h l)])) ``` .small[ .alt[Python version suggested by Dakai Tzou:] ```py from functools import reduce def join(l, sep): if l == []: return l def step(elem, accum): return elem + sep + accum return reduce(step, l[1:], l[0]) ``` ] </div> --- # Implementing reverse with foldl .col-7[ ### Original ```scheme (define (reverse l) (define (rev accum l) (match l [(list) accum] [(list h l ...) (rev (cons h accum) l)])) (rev l (list))) ``` ] -- .col-5[ ### Solution ```scheme (define (reverse l) (define (on-elem elem accum) (cons elem accum)) (foldl on-elem (list) l)) ``` or ```scheme (define (reverse l) (foldl cons (list) l)) ``` ] --- # Exercise > Write a function `(to-string l)` that takes a list of numbers > and renders them as `[n1, n2, ...]`. Example, `(list-to-string '(1 2 3))` > should output `[1, 2, 3]`. Function `number->string` converts a number > into a string -- ```scheme (define (to-string l) (string-append "[" (join ", " (map number->string l)) "]")) ``` 1. convert a list of string to a list of numbers (so that `join` can use the list) 2. convert a list of numbers into `1, 2, 3` 3. Surround the string with brackets.