title: CS450 layout: true author: Tiago Cogumbreiro lecture: 10 abstract: TypedRacket, thunks, and promises 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 # Module 4: # Lazy evaluation --- # Module 4 ## Lazy evaluation * TypedRacket: typing annotations on top of Racket * Using functions to delay computation * Lazy evaluation as a form of controlling execution * Lazy evaluation as data structures * Functional patterns applied to delayed evaluation --- class: impact # TypedRacket --- # Typing a factorial example .col-7[ ```scheme *1. #lang typed/racket *2. (: factorial (-> Number Number)) 3. (define (factorial n) 4. (cond [(= n 0) 1] 5. [else (* n (factorial (- n 1)))])) ``` ] .row[] ---- - *Line 1.* Specifies that we are using TypedRacket with `typed/racket` - *Line 2.* **Function signature:** `(: name-of-function (-> TypeOfArg1 TypeOfArg2 ReturnType))` - **Running a script is the same as with Racket.** Run `racket script.rkt` as usual! - Run `racket -I typed/racket` to start the TypedRacket REPL. - Write `#lang typed/racket/no-check` to disable type-checking (not advised). --- class: impact # Delayed evaluation --- # Recall the evaluation order ### Function application The evaluation of function application can be called *eager* * Evaluating a function application first evaluates each argument before evaluating the body of the function. ### Condition The evaluation of `cond` can be called *lazy*, in the sense that a branch of `cond` is only evaluated when its guard yields true (and only the one branch is evaluated). --- # How to encode an `if-then-else`? ```scheme (: factorial (-> Number Number)) (define (factorial n) (cond [(= n 0) 1] [else (* n (factorial (- n 1)))])) ``` -- ### Example .col-6.small[ ```scheme (: if (All [T] (-> Boolean T T T))) (define (if b then-branch else-branch) (cond [b then-branch] [else else-branch])) (: factorial (-> Number Number)) (define (factorial n) (if (= n 0) 1 (* n (factorial (- n 1))))) (factorial 10) ``` ] .col-1[ ] .col-5.box[ The type `(All [T] (-> Boolean T T T))` specifies a **type-parameter**, akin to a generic of Java or a template parameter of C++ ] .row[] > What is wrong with this implementation? -- > Why does `(factorial 10)` not terminate? --- # Our implementation of `if` is too eager Because our `if` is a function, applying it evaluates the `then-branch` and the `else-branch` before choosing what to return. This means our factorial no longer has a base case, and, therefore, it does not terminate. ```scheme = (factorial 0) = (if `(= 0 0)` 1 (* 0 (factorial (- 0 1)))) = (if #t 1 (* 0 (factorial `(- 0 1)`))) = (if #t 1 (* 0 `(factorial -1)`)) = (if #t 1 (* 0 (if (= -1 0) 1 (* -1 (factorial (- -1 1)))))) = ... ``` > Any idea how we can work around this limitation? --- # Using `lambda`s to delay computation > We can use a zero-argument lambda to hold each branch, as a `lambda` delays > computation! ```scheme (: if (All [T] (-> Boolean `(-> T)` `(-> T)` T))) (define (if b then-branch else-branch) (cond [b (then-branch)] [else (else-branch)])) (: factorial (-> Number Number)) (define (factorial n) (if (= n 0) (`lambda ()` 1) (`lambda ()` (* n (factorial (- n 1)))))) (factorial 10) ``` ---- - Now each parameter is of type `(-> T)`, a function that takes 0 arguments and returns a value of type `T` --- ## Typechecking errors .col-6.small[ ```scheme foo.rkt:8:2: Type Checker: Polymorphic function `if' could not be applied to arguments: Argument 1: Expected: Boolean Given: Boolean Argument 2: Expected: (-> T) Given: One Argument 3: Expected: (-> T) Given: (-> Number) Result type: T Expected result: Number *in:(if (= n 0) 1 (lambda () (* n (factorial (- n 1))))) ``` ] .col-6[ | # | Value | Expected | Given | |--|------|------|-----| | 1. | `(= n 0)` | `Boolean` | `Boolean` | | 2. | `1` | `(-> T)` | `One` | | 3. | `(lambda)` | `(-> T)` | `(-> Number)` | | | return | `T` | `Number` | - Ignore row when same type (Arg 1) - Ignore when type param `T` vs `Number` - .alt[Only interesting is `Argument 2`, `(-> T)` vs `One`, which is the type of `1`] ] --- # Thunks: zero-argument functions The pattern of using zero-argument functions to delay evaluation is called a *thunk*. You can use thunk as a verb which is a synonym of delaying evaluation. * `(lambda () e)` delays expression `e` * `(e)` evaluates thunk `e` and calls that thunk ??? > Notice that thunks are only possible because of lexical scoping and closures. --- # Using `thunk` Racket offers `(thunk e)` as a short-hand notation for `(lambda () e)`; both notations are equivalent. ```scheme (: if (All [T] (-> Boolean (-> T) (-> T) T))) (define (if b then-branch else-branch) (cond [b (then-branch)] [else (else-branch)])) (: factorial (-> Number Number)) (define (factorial n) (if (= n 0) `(thunk` 1) `(thunk` (* n (factorial (- n 1)))))) (factorial 10) ``` --- # Thunks for delayed evaluation - You can use `(lambda () some-computation)` to delay the evaluation of `some-computation`. - To initiate `some-computation` you need to run the lambda. - You can use `(thunk some-computation)` as a short-hand notation. - Using a lambda to delay computation also lets you run the same computation multiple times. ```scheme (: f (-> Number)) ; (define (f) (displayln "Called (f)") 0) ; <- equivalent (define f (thunk (displayln "Called (f)") 0 ) ) (f) ; Outputs: Called (f) (f) ; Outputs: Called (f) ``` --- class: impact # Functional patterns: promises --- # Repeated delayed computation > In functional programming, there are cases where you have an intertwined > pipeline of functions where a thunk might be carried around. Since we aim at > side-effect free programming models, it is wasteful to compute a thunk > multiple times, when at most one would do. ### Example ```scheme (define (runner count thunk call-back) (cond [(<= count 0) (call-back (thunk) thunk)] ; `invokes thunk once, and passes it along` [else (call-back count thunk)])) ; `does not invoke thunk` ``` > It might not be possible to know, at the function-level, if `thunk` was already > called, as it depends on the caller and, in this case, on `call-back` as well. --- # Promises: memoize delayed computation * `(delay e)` delays the evaluation of an expression (yielding a promise) * `(force e)` caches the result of evaluating `e`, so that multiple applications of that thunk return the result. > **Did you know?** > * Memoization: optimization technique that caches the result of an expensive function and returns the cached result > * Haskell does not share the same evaluation model as we have in Racket. > Instead, *all* expressions of the language are lazily evaluated. > * The idea of memoized delayed evaluation provides an elegant way to parallelize code. > The concept is usually known as a *future*. > * The idea of memoized delayed evaluation (promises) is also very important in asynchronous code (networking, and GUI), e.g., in JavaScript, in Python --- # Example: `delay`/`force` <div class="col-6" markdown=1> ### Thunks ```scheme (define (thunk-repeat n th) (cond [(<= n 0) (void)] [else `(th)` (thunk-repeat (- n 1) th)])) (thunk-repeat 3 (`thunk` (sleep 1) 3)) ``` </div> <div class="col-6" markdown=1> ### Promises ```scheme (define (promise-repeat n prom) (cond [(<= n 0) (void)] [else `(force prom)` (promise-repeat (- n 1) prom)])) (promise-repeat 3 (`delay` (sleep 1) 3)) ``` </div> --- # Promises versus thunks ### Accessor * Promises: must call function `force` * Thunks: call the object itself ### Evaluation count * `(force p)` evaluates the promise at most **once**; subsequent calls are cached * `(th)` calling a thunk evaluates its contents **each and every time** --- class: impact # Implementing promises --- # Implementing promises: state > Promises are usually implemented with mutable references. > Can we get away with implementing promises without using mutation? A promise has two states: 1. when the thunk has not been run yet 2. when the thunk has been run at least once A promise must hold: * the thunk we want to cache * the empty/full status We need to separate the operations that mutate the state, from the ones that query the state. --- # Implementing promises: operations Function `(force p)` can be thought of as a few smaller operations: 1. checking if the promise is empty 2. if the promise is empty, update the promise state to full and store the result of the thunk 3. if the promise is full, does nothing to the promise state, and returns the cached result Let us separate the operations that change the state from the ones that return the value. * Function `(promise-sync p)` returns a new promise state. When the promise is empty, it computes the thunk and stores the result in a full promise. When the promise is full, it just returns the promise given. * Function `(promise-get p)` can only be called when the promise is full and returns the result of the promise. --- # Immutable promise implementation ```scheme (struct promise (empty? result)) (define (make-promise thunk) (promise #t thunk)) (define (promise-run w) (define th (promise-result w)) (th)) (define (promise-get p) (cond [(promise-empty? p) (error "promise: call (promise-sync p) first.")] [else (promise-result p)])) (define (promise-sync p) (cond [(not (promise-empty? p)) p] [else (promise #f (promise-run p))])) ``` --- # Example of immutable promises ### Immutable Promises ```scheme (define (promise-repeat n prom) (cond [(<= n 0) (void)] [else (promise-repeat (- n 1) (`promise-sync` prom))])) (promise-repeat 3 (make-promise (`thunk` (sleep 1) 3))) ``` ### Standard promises ```scheme (define (promise-repeat n prom) (cond [(<= n 0) (void)] [else `(force prom)` (promise-repeat (- n 1) prom)])) (promise-repeat 3 (`delay` (sleep 1) 3)) ```