We can now move on to our next closure idiom which are callbacks. Callback style programming is very common these days. The idiom we're using here is that someone writes a library that takes in from clients functions that should be called later when some sort of event occurs. So example libraries are things that control the keyboard or the mouse or when data arrives from the network. So programs may want to know. may want to act on, keys being pressed on the keyboard. And so what they will do is pass to the library code that should execute when a key is pressed. So we really want first class functions for this so we can pass in some code that should be called later when an event occurs. And that's called a callback. That doesn't have to be this out external data like a keyboard or data from the network. Sometimes we write games in this style. Some player in the game maybe an automatic player should register code that should be called when it's that player's turn to move around in some virtual world. Now the way these library should work is they should accept multiple callbacks. There may be many different parts of the program that all need to know when keys are pressed on the keyboard and they need different data to act on. So we don't just need to pass first class functions. They need to be closures so that each client passing in a callback can use the private data, the bindings in the environment where the function was defined, to have access to the data it's going to need when the callback executes. So this is where closures are really valuable. It's important that that private data not show up in the type of the callback because the library implementer has no idea what that data should be. Now object-oriented languages for those of you that are used to them also handle callbacks, they do it with objects. I find closure is just as elegant if not more elegant and you can learn the idea of callbacks either way. So since we're setting functional languages here we'll do it that way. So we are going to use mutable state in our library and I'm going to argue that's appropriate here. Our library is going to keep track of all the callbacks that have been registered, all the code that should execute when an event occurs. And when a new one gets registered we really do want to update state so that we can have more things, you know, we can keep track of what we are supposed to do. So our library is going to maintain that mutable state for what callbacks are there and it's going to provide a function for adding a new one to that mutable collection. Now real library of course would have lots of other features like for removing a callback that was previously added. And we're just going to take a very simple approach that what clients are going to pass us are functions of type int arrow unit. So you can think of that int as encoding which key on the keyboard was pressed. Maybe A is one, B is two, that sort of thing. So the only public interface to our library is going to be this function onKeyEvent. It's going to say when a key event occurs you want me to call this int arrow unit you passed and I will give back to you the int corresponding to what key was pressed. So onKeyEvent takes an int arrow unit, there's no result here, the unit type has no useful content. And the result of onKeyEvent is just the side effect that I'll call you back later. So there is no useful result. So the result here is also unit. Okay? So that's the entire interface. Now we just need a library that will implement that interface. So here it is, it's in the code file as well but it all fits on the slide. The library is going to internally maintain a mutable reference that holds a list of all the callbacks that have been registered. So we'll initialize that mutable reference to have contents empty list because none have been added yet. Then when someone calls onKeyEvent with a function we will assign to cbs, for callbacks, this list which is made out of consing f onto the previous contents of cbs. So this is updating cbs to refer to a list with one more element than it used to. Perfect. Then when some event actually occurs, so you know the key is actually pressed. Let's assume that this function on event is called with a number. I'm not actually going to show you in ML how to actually hook up to the keyboard. We're going to fake it through this function, we're just simulating the idea. And all this function does, I will not explain the details to you, is take the contents of cbs as you see here with the exclamation point and go through and call each of the functions. Right? So for each function in that list we will call it with i that's exactly what a callback library is supposed to do. So that's the library. And remember all clients are going to do is call onKeyEvent with appropriate functions. So here are a couple example clients and they're always going to pass enclosures that do what they need to do. So here's my first client here OnKeyEvent. It actually ignores the integer it's given and all it does is increment this timesPressed variable. So the reference that timesPressed refers to. So timesPressed refers to an int ref, the contents are initially zero and we register here a callback that every time it's called it takes timesPressed and updates it to previous contents of timesPressed plus one. So this is a logger that is counting how many times keys have been pressed. Here I have a function that every time you call it registers a callback. And what it does is when you call printIfPressed with i it registers a callback that says i, if you give me back j, so j was the key that was pressed. If i equals j I'll print out a message saying you pressed i, otherwise I'll do nothing. I only care about the cases where it's i that was pressed. All right. So that's all good. Over here in the code I have all the code I just showed you exactly how I showed it to you. And then here at the bottom I used that function printIfPressed to add four more callbacks one for four. So that will print out you pressed four if indeed four was pressed, one for 11, one for 23, one for four. And so with this one up here that keeps track of how many have been pressed we'll have five total callbacks registered because we call onKeyEvent five times so that list will have five things in it. So let's just load it all up and it all loads it's all fine. We can see that by the time the REPL prints cbs the contents actually is five functions, it's a list with five elements. And nothing has been printed yet. And if I ask timesPressed I get zero because there haven't been any events yet. So now we're going to simulate events happening with this onEvent function. So when I call onEvent with a number it's going to pass that number back to all the closures that were registered with OnKeyEvent. So if I pass in 11 it prints you pressed 11, because one of those five callbacks chose to print that. The other printIfPressed did nothing. TimesPressed by the way is now one. So it really did call that code. We could do onEvent 79, nothing gets printed. No one wanted to print that. We could do onEvent four, that prints it twice because two of our callbacks chose to print that string. So that's fine. We could do onEvent 23, it prints once. We could at any time ask timesPress that's been incremented every time thanks to one of our callbacks and four because we did four events. I think we did 11, 79, four, and 23. All right? So that's callbacks.