We can now move on to our next Closure Idiom which are Callbacks. Callbacks style programming is very common these days. The idiom we're using here is, that someone writes a library It 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. It 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 not players turn to move around in some virtual. The world. Now the way these libraries 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 callbacks executes. So this is where closures are really valuable. It's important that that private data not show up in the type of the callbacks, 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 closures 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. [SOUND] 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 a real library, of course, would have lots of other features like for removing a callbacks 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 about INT as encoding which key on the keyboard was pressed. Maybe a as one b as 2 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 interal-unit you passed and I will give back to you. The int corresponding to what key was pressed. So on key event takes an int arrow unit. There's no result here. The unit type has no useful content. And the result of on key event is just the side effect that, I'll call you back later. So there's no useful result. So the result here is also a 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 would have been registered. So we will initialize that mutable reference to have contents empty list, because not have been added yet. Then, when someone calls on KeyEvent with the function we will assign to see these for callbacks. This list, which is made out of conzing f on to the The previous contents of CBs. So this updating CBs to refer to a list with one more element than it used to. Perfect. Then, when some event actually occurs, so sorry, 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 an ML. How to actually hook up to they 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 CB's, as you here, 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 call back library is supposed to do. So that's the library and remember, all clients are going to do is call onKeyEvent with appropriate functions. [SOUND].So here are a couple example clients, and what, they're always going to pass in closures that do what they need to do. So here's my first client here, onKeyEvent, it actually ignores the integer it's given and it all it does is increment. This times pressed variable. So, sorry. The reference that times pressed refers to. So times pressed refers to an int ref. The contents are initially zero. And we register here, a callback, that, every time it's called. It takes times pressed, and. Updates it to previous contents of times pressed plus 1. 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 if you give me back J. So J was the key that was pressed. If I=J, I'll print out a message saying you pressed I. Otherwise, I'll do nothing. I, I only care about the, the cases where it's I that was pressed. Alright, 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 use that function print, if pressed, to add 4 more. Callbacks, one for 4, so that'll print out, you pressed 4, if indeed 4 was pressed, one for 11, one for 23, one for 4, and so with this one up here, that keeps track of how many have been pressed, we have, we'll have 5 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, it actually, the content actually is five functions, it's a list with five elements. and nothing has been printed yet, and if I ask timesPressed, I get 0. 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 shows to print that. the other printed press did nothing. Times pressed, by the way, is now 1. So it really did call that code. We could do on event, 79. Nothing gets printed. No one wanted to print that. We could do on event. For that prints it twice because two of our callbacks chose to print that string so that's fine. We could do on event twenty three it prints once we could at any time as times pressed that's been incremented every time thinks one of our callbacks and four because we did four of that. I think we did 11, 79, 4 and 23. Alright? So that's Callbacks.