title: CS450 layout: true author: Tiago Cogumbreiro lecture: 4 abstract: Recursion, nested definitions 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 # {{title}} ## Structure of Higher Level Languages ### Lecture {{lecture}}: {{abstract}} ### {{author}} --- class: impact # Exercises with lists --- class: full # A template of recursion .col-6[ ### Copying a list ```scheme (define (copy l) (match l [(list) ; input = '() `(list)` ; expected output = '() ] [(cons h l) ; input = (list 1 2 3) ; h = 1 ; l = (list 2 3) (define result (copy l)) ; result = (list 2 3) `(cons h result)` ; expected output = (list 1 2 3) ])) ``` ] .col-6[ ### Notes - `(define (copy l) l)` would be a simpler solution, but we're trying to illustrate a **recursion pattern**. - Remember to write the expected inputs and outputs for a given example - **Part in yellow:** given the expected inputs, how would you build the expected output? ] --- # Lists: example 1 ### Summation of all elements of a list ## Spec ```scheme (require rackunit) (check-equal? 10 (sum-list (list 1 2 3 4))) (check-equal? 0 (sum-list (list))) ``` --- # Lists: example 1 ### Summation of all elements of a list <div class="col-7" markdown> ## Solution ```scheme (define (sum l) (match l [(list) ; input = '() `0`] ; expected output = 0 [(cons h l) ; input = '(1 2 3 4) ; h = 1 ; l = '(2 3 4) ; result = (sum (list 2 3 4)) = 2 + 3 + 4 = 9 (define result (sum l)) `(+ h result)` ])) ; expected output = (+ 1 9) = 10 ``` </div> .col-5[ ## Notes - We use the same pattern as in `copy` - Again, the expression being returned combines `h` and `result` ] --- # Spot the error! (#1) ```scheme #lang racket (define (sum-list l) (match l [empty 0] [(cons h l) (+ h (sum-list l))])) ``` --- # Spot the error! (#1) ```scheme #lang racket (define (sum-list l) (match l [`empty` 0] [(cons h l) (+ h (sum-list l))])) ``` - For `match` consider `empty` to be defined as `(define empty (list))`, not as a keyword - Pattern `empty` means: anything you find assign it to a variable called `empty`; same as writing `[x 0]` - The first branch matches with anything you give it, so this function never recurses --- # Spot the error! (#2) ```scheme #lang racket (define (sum-list l) (match l [(list) 0] [(cons h t) (+ h (sum-list l))])) ``` --- # Spot the error! (#2) ```scheme #lang racket (define (sum-list l) (match l [(list) 0] [(cons h t) (+ h (sum-list `l`))])) ``` - We wanted to recurse on `t`, but instead recursed on the original list `l` - This leads to an **infinite loop** - **Good practice:** use `l` as the rest of the list, and make this error impossible. --- # Spot the error! (#3) ```scheme #lang racket (define (sum-list l) (match l [(list) 0] [(h l) (+ h (sum-list l))])) ``` --- # Spot the error! (#3) ```scheme #lang racket (define (sum-list l) (match l [(list) 0] [(h l) (+ h (sum-list l))])) ``` - We forgot to specify the data-type `cons` in the second pattern - Racket will raise an exception notifying us that the pattern is incorrect ```scheme ex.rkt:5:5: match: syntax error in pattern in: (h l) location...: ex.rkt:5:5 ``` --- # Lists: example 2 ### Returns a list from n down to 1 ## Spec ```scheme (require rackunit) (check-equal? (list) (count-down 0)) (check-equal? (list 3 2 1) (count-down 3)) ``` -- ## Solution ```scheme #lang racket (define (count-down n) (cond [(<= n 0) (list)] [else (cons n (count-down (- n 1)))])) ``` --- # Lists: example 3 ### Point-wise pairing of two lists ## Spec ```scheme (require rackunit) (check-equal? (list (cons 3 30) (cons 2 20) (cons 1 10)) (zip (list 3 2 1) (list 30 20 10))) (check-equal? (list (cons 3 30) (cons 2 20) (cons 1 10)) (zip (list 3 2 1) (list 30 20 10 `5 4 3 2 1`))) (check-equal? (list (cons 3 30) (cons 2 20) (cons 1 10)) (zip (list 3 2 1 `90 180 270`) (list 30 20 10))) ``` --- # Lists: example 3 ### Point-wise pairing of two lists -- ## Solution .col-6[ ```scheme #lang racket (define pair list) ; Encode a pair as a list (define (zip l1 l2) ``` ] -- .row[] .col-6[ ```scheme (match* (l1 l2) [((list) _) (list)] [(_ (list)) (list)] [((cons h1 l1) (cons h2 l2)) (cons (pair h1 h2) (zip l1 l2))])) ``` ] .col-6[ - Use `match*` to pattern match two values at once ] --- class: impact # Using nested definitions --- # Build a list from 1 up to n > Our goal is to build a list from 1 up to some number. > Here is a template of our function and a test case for > us to play with. For the sake of simplicity, we will > not handle non-positive numbers. ```scheme #lang racket (define (countup-from1 x) #f) (require rackunit) (check-equal? (list 1) (countup-from1 1)) (check-equal? (list 1 2) (countup-from1 2)) (check-equal? (list 1 2 3 4 5) (countup-from1 5)) ``` > Hint: write a helper function `count` that builds > counts from `n` up to `m`. --- # Exercise 1: attempt #1 > We write a helper function `count` that builds counts from `n` up to `m`. ```scheme #lang racket (define (countup-from1 x) (count 1 x)) (define (count from to) (cond [(equal? from to) (list to)] [else (cons from (count (+ 1 from) to))])) ``` -- .space-top.center[ ## Let us refactor the code and hide function `count` ] --- # Exercise 1: attempt #2 > We move function `count` to be internal to function `countup-from1`, as it is > a helper function and therefore it is good practice to make it *private* to > `countup-from1`. ```scheme (define (countup-from1 x) ; Internally defined function, not visible from ; the outside * (define (count from to) * (cond [(equal? from to) (list to)] * [else (cons from (count (+ 1 from) to))])) ; The same call as before (count 1 x)) ``` --- # When to nest functions? Nest functions: * If they are unnecessary outside * If they are under development * If you want to hide them: **Every function in the public interface of your code is something you'll have to maintain!** --- class: full, center, middle # Intermission: # Nested definitions --- # Nested definition: local variables > Nested definitions bind a variable within the body of a function and are only visible within that function (these are local variables) ```scheme #lang racket (define (f x) (define z 3) (+ x z)) (+ 1 `z`) ; Error: z is not visible outside function f ``` --- # Nested definitions shadow other variables > Nested definitions silently shadow any already defined variable ```scheme #lang racket (define z 10) (define (f x) (define `x` 3) ; Shadows parameter (define `z` 20) ; Shadows global (+ x z)) (f 1) ; Outputs 23 ``` --- # No redefined local variables > It is an error to re-define local variables ```scheme #lang racket (define (f b) ; OK to shadow a parameter (define b (+ b 1)) (define a 1) ; Not OK to re-define local variables * ; Error: define-values: duplicate binding name (define a (+ a 1)) (+ a b)) ``` --- class: full, center, middle # Back to Exercise 1 --- # Exercise 1: attempt #2 > Notice that we have some redundancy in our code. > .alt[In function `count`, parameter `to` remains unchanged throughout execution.] ```scheme (define (countup-from1 x) ; Internally defined function, not visible from ; the outside (define (count from `to`) (cond [(equal? from to) (list to)] [else (cons from (count (+ 1 from) `to`))])) ; The same call as before (count 1 x)) ``` --- # Exercise 1: attempt #3 > We removed parameter `to` from function `count` as it > was constant throughout the execution. Variable `to` > is captured/copied when `count` is defined. ```scheme (define (countup-from1 to) ; Internally defined function, not visible from ; the outside (define (count from) (cond [(equal? from `to`) (list `to`)] [else (cons from (count (+ 1 from)))])) ; The same call as before (count 1)) ``` --- # Example 1: summary * Use a nested definition to hide a function that is only used internally. * Nested definitions can refer to variables defined outside the scope of their definitions. * The last expression of a function's body is evaluated as the function's return value --- class: impact # Measuring performance --- class: full, center, middle # Example 2 ## Maximum number from a list of integers --- # Example 2: attempt 1 > Finding the maximum element of a list. ```scheme #lang racket (define (max xs) (cond [(empty? xs) (error "max: expecting a non-empty list!")] [(empty? (rest xs)) (first xs)] ; The list only has one element (the max) [(> (first xs) (max (rest xs))) (first xs)] ; The max of the rest is smaller than 1st [else (max (rest xs))])) ; Otherwise, use the max of the rest ; A simple unit-test (require rackunit) (check-equal? 10 (max (list 1 2 10 4 0))) ``` > We use function `error` to abort the program with an exception. --- # Example 2: attempt 1 > Finding the maximum element of a list. Let us benchmark `max` with sorted list (worst-case scenario): * 20 elements: 18.43ms * 21 elements: 36.63ms * 22 elements: 75.78ms > Whenever we add an element we double the execution time. .alt[Why?] --- # Example 2: attempt 1 > Whenever we hit the else branch (because we can't find the maximum), > we re-compute the max element. ```scheme (define (max xs) (cond [(empty? xs) (error "max: expecting a non-empty list!")] [(empty? (rest xs)) (first xs)] ; The list only has one element (the max) [(> (first xs) `(max (rest xs))`) (first xs)] ; The max of the rest is smaller than 1st [else `(max (rest xs))`])) ; Otherwise, use the max of the rest ``` --- # Example 2: attempt 2 > We use a local variable to cache a duplicate computation. ```scheme (define (max xs) (cond [(empty? xs) (error "max: expecting a non-empty list!")] [(empty? (rest xs)) (first xs)] [else * (define rest-max (max (rest xs))) ; Cache the max of the rest * (cond * [(> (first xs) rest-max) (first xs)] * [else rest-max])])) ``` * Attempt #1: 20 elements in 75.78ms * Attempt #2: 1,000,000 elements in 101.15ms --- # Example 2 takeaways * Use nested definitions to cache intermediate results * Identify repeated computations and cache them in nested (local) definitions