 Okay, do we have everybody? I think we do. Is this starting time, Liz? Is this starting time? Welcome. I'm Jonathan. It's very nice to be here at the Dutch for Work Trouble together. I've missed this for the last couple of years and It's very good to be back. So today I'm going to talk for you on reactive programming. This is something I've been very excited over recent years. It's something that I've been bringing to the world of 12.6 over the last year or so, and there's a lot of very exciting stuff to talk about. Now, the topic really that I want to address today is the way we deal with asynchronous stuff, okay? What do we do about asynchronous stuff? I mean, data just arrives when it damn pleases. So we're talking about UI events, okay? We don't get to choose when the user clicks the button or types in the text box they will do it whenever they feel like. We're talking about things like web requests, okay? If we are server, the web request will arrive whenever the user makes the web request, and we don't really have much choice in the map. If we're making web requests ourselves, the response will come back, you know, whenever it feels like it. We have all kinds of other sources of asynchronous data, too. You know, things like file change notifications, okay? So I can get my operating system to tell me, oh, you changed that file. I'd better, you know, notify you of this change. Things like timers, okay? It's something that ticks every second. Tick, talk, tick, talk, okay? We're going to do something about it. Unique signals. All of these are things that just happen. And dealing with them is kind of fun, especially when you start getting multiple sources of them. Because when you start getting multiple sources of asynchronous data, you get into all of these interesting synchronization problems. All of these problems where you want to make sure that you're not maybe doing two things at the same time. And you get really horrible things. Look at this little autocomplete thing here. Okay, this is what people apparently search for on Google. I'm a little concerned about the second one. But I'm glad more people want to do it than the third. Anyway, basically what can happen with these things, if you've implemented one of them, is, you know, the user types something. And you send off a HTTP request, okay? And, you know, on the server it starts thinking about this. And then the user changes what they've typed. So you send off another HTTP request. And it turns out that the second one gets an answer really, really fast. Okay, maybe you hit a different server that's less loaded, or something like that. So when you get back to the results of this latest thing, the user typed. And you update the data that is there in the drop-down. And everything is really good. And then the first web server that you contact, it comes back, gives you more results. Okay? And what do you do? Well, if you have a program link carefully, what you're going to do is end up replacing the latest data in terms of, you know, what the user wants to see with the data that you just got back from this older request. And doing all of these sorts of things gets really kind of fun and tricky. Now, you might wonder, am I going to be talking about threads in all of this? And the answer is, well, sometimes they may be involved. Yes. If you kick a bit of work off on another thread to do it in the background, perhaps because you're building a training user interface and our users expect responsive applications now. Okay, they don't expect that they say, do this. And then the UI freezes up for like 10 seconds. And they're like, er, er, er, er, I hate your application. Okay, we don't know that. We should work off onto other threads. But that data comes back whenever it likes. And the user might be doing something else when it comes back. And we need to deal with all the synchronization issues there. So there's lots and lots of things to worry about when we start doing asynchronous programming. And generally the reaction traditionally to this is, okay, or maybe more like, er, er. So before we try and take this off, let's talk a little bit about something more familiar. And how we deal with the problems that it, er, it gives us some facts against. This is the one bit of Pearl 5 in my talk. It's er, it's a while loop. Reading a file, I hope it's correct. I don't write much of this anymore. But er, the thing to note about this is that it basically is going through the file line by line. At some point, you know, we will block, maybe we'll be waiting for the disk, okay, to slowly churn around and give us some more data much slower than the CPU. So the real pattern at the heart of this is what we call the iterator pattern. Okay, we, we have this data and we're working our way through it step by step by step. Line by line by line in the case of a line based file. Now, if we consider, er, lists of things, er, you know, if we're working with arrays, lists, we don't just have to do it all by writing loops and if statements and doing the normal imperative programming stuff. As we tend to get a little bit more, you know, skill with developers, we start reaching to, because let me hire all the tools, er, things like map. Okay, so in map, if you think about what map is doing, it's basically creating a new array, doing a reach loop, running your piece of code, okay, and er, then just, just showing the results of that, that code block into the new array. And that's what the map does. The graph is kind of similar apart from there's an if that. These things factor the flow control out of that code. And er, we, we kind of like that, er, I guess, and we, you know, we, we maybe go using them. Er, actually we like these a real lot in PeltSex and we've got a whole bunch more of them. If you walk me through this example, er, we're getting the gold members of, say, our frequent flyer program. And then er, what I'm doing is I'm graphing out those who have more than er, 10,000 points. And er, that startup point syntax there basically is er, creating us a little closure. Okay, so er, that's like a dollar underscore er, dot points. Er, but er, without writing a dollar underscore. And it actually realizes that it should drag that, er, greater and operate it into the, the whole thing as well. So you, you basically get a little closure in there. Er, so anyway, er, even forgetting that it's, it's fairly clear, I think, what, er, what it's trying to achieve. Er, then we've got a whole bunch of entrants to add a little competition. We pick 10 of them. That's just grabbing 10 at random. Okay, there are winners. And then we just use math to grab the name of each of those, those winners. Er, now er, you know, that's, that's fairly nice. And you might say, well, how does this relate to the iterator pattern? And the answer is, well er, in full six, our lists are lazy. Meaning that you can actually have an array and work through it a piece of the time, or an element of the time. In fact, you can even have infinitely long lists. For example, that is an infinite list of the Fibonacci numbers. Er, now of course er, we don't have enough memory to store infinite lists. Er, so, you know, er, this is a little challenging. Er, but you'll notice there that I've actually used the bind operator. Okay, which is your hint that something a little bit unusual is going on. Er, now, one of the big cultures when you start putting laziness into programming languages is people don't expect things to go executing later than they kind of intuitively think they will. Er, so, for that reason, we've typically kept assignments as being what we call mostly eager. Er, meaning that, you know, we don't sort of randomly go and er, just say, oh, we can't be bothered to execute this bit of code sort of later and then sort of catch everyone out because they wrote side effects everywhere. Er, you know, we don't expect code problems to be sort of Haskell level purity or something. Er, but er, when we do want that, we go and stick our column in there and what that means is I just want to talk about this list and then I can go and grab it. Okay, and I'm not actually doing any work here. In this graph, what I'm saying is I would like to set up a thingy. Now, if I ask it for values, we'll grab values from Fibs, which is a sequence. Okay, the numbers 1, 1, 1 plus 1 is, you know, 2, er, 2 plus 1 is 3, 3 plus, er, sorry, 2 plus 3 is 5, okay, and so on. Er, and er, we're just grabbing those out there and we're just indexing into it, we're getting numbers up to 10. That's actually syntax for a range, okay, 0, 0.9. And er, you're kind of looking at this and you're saying, well, okay, that's kind of nice because it means that er, we can talk about it from the long sequences of things but just, you know, consider the ones we care about. Er, the only problem being, of course, that you're like, well, what the hell, I'm a real programmer. I never use the Fibonacci numbers in my programs. Er, why do I care about this? Okay, well, that's a really good question. The reason you might care about this is because we can do this with files. So you can actually write a for loop, okay, over a file handle, grabbing in its lines. Er, you can even grab it like this and it's not going to pull the whole thing into memory. It's just going to let us step a line at a time, filter out the wants and start with comments, okay, and put each one into dollar line. You'll see that the variable goes over here. In Pulsex, we've got rid of some of the friends, okay, but er, what we're doing there is we're just going through the lines of the file. And er, that's kind of nice. That's a much more practical use of laziness. And er, it means we can, we can now actually just go and start grabbing, er, you know, however long lines that we get from files without having to care if it's a really big file, we can just work through it a bit at a time. So, one of the things that you note about all of these things is that it's de-facto outflow control. Okay, they sort of take this, this sort of looping this, er, conditional stuff and they drag it out of our code and they let us just write it once. And of course some mapping, Greg, it's not a lot of code, but it's like pick where you want to pick ten things at random, but without duplicates, er, there's some sort of harder math in there. But then we get things like unique, unique filters out duplicates. Inside of unique, by the way, the ads is just specifying the, er, the thing I want to make unique in all of them. So here I've got a bunch of, say, search results from Google and Bing and er, I want to just make sure I get unique ones. I want to toss the overlaps, okay? So if they both gave the same URL back to something, we'll er, we'll just have it in the results once. But er, the thing about this is that inside of unique, there's actually a hash and er, it's going and it's storing the, you know, the things that we already saw and er, that one is actually dragging not only flow control out of that code, but also state. So we don't have to think about all of that, you know, those variables. I mean, we, we talk a lot about, you know, global variables are bad, why are they bad, because they can change everywhere. Er, so then we try and put things into classes and make them attributes. Er, but of course we don't make things an attribute if a local will do, we don't declare a local start of a subroutine if it's just needed in one if block. We do all of these things because actually state makes programs harder to read. Er, when we start using things like say unique where we can talk about oh, I want a unique list of these things, we get to get the state and er, you know, hide it away and er, not have to care about it quite so much. Now, one of the things that, you know, I kind of got thinking about all of this is er, what if we could do this for er, react for er, you know, asynchronous data, okay? All of the er, the stuff that we've talked about so far is synchronous. So when I had the list of the Fibonacci numbers, you know, I'm sort of down on me and he's like, give me another Fibonacci, okay? And er, slowly my program gives me them. And it's the same with the file, I mean, they're begging the file system for more and more data and lines of the file off disk. And er, if it, you know, isn't quite ready yet, I have to sit there and wait. Okay, I'm blocking. And er, databases are like this. As well you go and you sit, waiting, okay, waiting, waiting. And that's the very nature of synchronous programming and synchronous data. Yeah, you know, we ask for it, we wait for it, we get it. But asynchronous data is different. It's this data that can just come and occur at any time. And one of the things that we might wonder is er, you know, is there a way that we can perhaps, you know, take some of these ideas and er, you know, factor out the complexity. So we can do asynchronous programming, but just like very synchronous programming of lists of data, we use things like grep and map and unique to, to not have to talk about the exact details of what we want. You know, what if I could do a grep on a stream of data and it's just being thrown at me? Okay, what if I could take a bunch of mouse clicks and just grep out the left clicks, okay? It's kind of an intriguing idea. Because if we can do that then, you know, we can drag the complexity out of things. We can hopefully bring together different sources of asynchronous data. I mean, we know there's things we can do with a list to bring them together. If I have two lists, I can zip them. There I can make one result list, which contains hair-wise combinations of the other two. So if I have two sets of numbers in two lists, I can, you know, maybe take them and add each number hair-wise together and get a single result list out. That's a zip operation. So, you know, there's lots of ways of doing that with synchronous lists. Maybe we can do that with asynchronous ones too. That would be really nice. And, you know, in theory, if we can tackle all of these things, we might even be able to get to the point where things that feel complex, like taking a piece of work, getting it done on another thread, and updating the user interface in a safe way with the result, that sort of thing might actually be kind of made easy. So there's all kinds of possible, you know, little benefits we could get, probably some other crap as well, okay? But the thing is, now, how can we get that? Well, some years ago, this joke's only funny if you know supplier and category theory. That's a very select audience, isn't it? Yeah. Anyway, category theory is this really strange bit of mathematics. I actually got a friend who's reading a lot of category theory at the moment, and it's kind of a thin line, but no matter if he's still sane or not, I'm never quite sure. He sort of tells me things about, you know, the end of funksters, oh, I'm low on ad, and I'm just like, yeah, let's go drink beer. But anyway, this apparently can give some quite nice insights. And one of the things it's really good at is revealing relationships between things that we maybe hadn't realized before. Several years back, a bunch of very smart guys, Eric Meyer and Anderson, basically realized that there's a relationship, a very deep one, between iterators, that is things we use in synchronous programming, you know, with lines, give me another line, give me another line, okay? And observers, what are observers? Well, the observer pattern is when you go to something like, say, a text box, and you say, here's a piece of code, call it back whenever the text in the text box changes. Okay, whenever we change that bit of text in the text box, we get a notification, okay? So, the thing that we're observing, we call it observable, just like the thing you can iterate, we call it this rule. And, you know, the thing we get as an iterator, well, the thing that gets called back as an observer, it's observing the changes to the text box. And if you think about it, that's asynchronous, okay? The observer doesn't have any choice about when he gets caught. It's all about the text box saying, oh, hey, I got some text. Ooh, I'll better, you know, call my observers and tell them. It's all asynchronous. And what they realize is that these two are, they call them categorical jewels. Now, without getting into what that means, because they'd really rather not, the big result that comes out of this is that anything you can sensibly define in terms of iterators, you can also sensibly define in terms of observables. That means that deep down in the map, there's something telling us that, yes, we can do map on a list, but we can also do map on an observable. We can do graph, we can do unique, we can do a squish, we can do all these different things. That's kind of exciting, because what it unveiled was that we actually can deal with asynchronous data, okay, in a very kind of familiar way. We can use a lot of the same mechanisms that we used to for dealing with synchronous data. They call this reactive programming, and synchronous programming got recoined as interactive programming, okay. But that one kind of got ignored, so reactive programming is the term that we pretty much always use to describe this kind of thing, okay. It's essentially programming where stuff happens and other things react to it as a result. So, let's actually get into the practicalities of doing this. So in PEL6, we have a type called supply. A supply is something that you can observe. And it's actually you tap the supply, okay. It's a little like a beer barrel. And when you want to beer, you go and, you know, open the tap and the nice stuff flows out, okay. And later, of course, your class might be full, so then you hopefully close the tap. And it kind of works in exactly the same way here. So here I have a supply, okay. And this actually is the interval supply. It's something that gives me a tick every time interval, every second in this case. Now, what I can do with that is I can take this little tick and I can just tap it and I can just say, oh, we started a couple of seconds ago. And actually what that's going to do is it's just going to start at 0, 1, 2, 3, et cetera, once per second. The thing about this is that because it's just a set of observables, we can map it. And the thing to realize about this map is that what we're actually doing is we're mapping the future, okay. We're talking about the map on things that haven't happened yet. And what happens is the flow control goes the opposite direction. This is very typical of Joules. The way Joules work is you basically separate, sorry, swap around your inputs and your outputs, okay. So what happens here is that every time you get a tick, then the map is run and the result of the map is then pushed on downwards, in this case into this save, okay, I just grabbed the save function there. And what happens is we get a zero in, we get tick, talk, tick, talk, et cetera. So, well, okay, we map it. So, fine, this looks kind of interesting. One thing you might wonder at this point is, you know, how does that interval thing work? Does it involve threads in any way? The answer is that yes, that one does. When you get that callback, that little save there, okay, this is actually all running up on a thread pool. So, yeah, we have real threads. And, you know, that one goes off. This, on the other hand, does not. There's sort of a principle of minimum concurrency. So here, I create a supply. You don't have to obtain one from something like Interball or one of the many, many other factories for them. You can actually just create one. And you can just start spewing data out on it. You call more, say, here's another bit of data, here's another bit of data, okay. And there's also done and quit, which are for the science now. But what we can do is we can just tap that. And as many things can tap it as they want. And what will happen is every time I push a, in this case, a Chime, a Duvel, down to this, okay, it will just run that little block there, okay. Now, this doesn't actually involve any threading at all. It doesn't just go and magically introduce it just because I started using a supply. Okay, so this is not necessarily about threading. And there's not going to be threads introduced for you just magically. You actually have to use something that, for example, involves time where we actually, you know, you're going to go and get on with stuff and then we're going to have these ticks coming through to actually start getting into having threads. Okay, so that was just some, you know, introduction to what we can do. But what I want to do for the rest of the session is we're going to be building two, sort of slightly more real world things using React's program. Now, who uses Git? Yes, Git is awesome. I love Git. Okay, I actually get to teach Git as well. It's a fun job. The nice thing about teaching Git, by the way, is it's got one really simple data structure at the heart of it. You can explain everything in terms of that. That's always a good system design. So, one of the things that I like about Git is that you basically can't lose stuff. You know, once you give something to it, it's essentially immutable. You might lose a reference to it, but then you can go and recover it somehow later on. And it's very hard to actually lose your stuff. However, that only applies once you've talked Git about your stuff, once you've committed your stuff. What happens in the in-between time? Are I changed stuff and, you know, maybe I, you know, I do something I regret. Say I do a change and then I somehow wipe it out and I can't get it back. It might almost be nice just to have something that, you know, between commits just makes me a little backup. So, I built one. Let me just go and demo it to you. So, what I'll do, I'm actually in a Git repository here. And when I just pull this thing up, it tells me the way that I can use it. What I'll do is I'll just tell it to watch. And that tells it that I wanted to watch the current directory. Now, what I'll then do is I'll just go and we'll actually create a file. This is going to be extremely creative. Oops. There we go. Okay. And if I just go and look over here, it tells me that it's back to bar. Actually, I did it twice because I touched the file the first time. And then again, what other files do I got in here? I think I've got an XP6. Let's just put something into that as well. Okay. And echo. Echo. I didn't do enough coffee today, apparently. So, what I can then say is intercommit list. And what it will tell me is that there's these four things that are recorded and I can then intercommit show, say, two. Okay. And it will say, oh, that was food. If I was to go and now make a git commit of XP6, okay, and some awesome message, oh, it's awesome, I titled it. Great. What we should notice over here is that it noticed and the head moved, okay, I committed, so it's gone and cleared away my backups. So, that seems kind of nice. So, how do we build it? Modern operating systems provide us with what we call IO notifications. That is, they tell us when something changed. If you think about it, this isn't a synchronous source of data. And we actually exposed this in Peltex. That's an IO notification class. You can say, watch path. If you give it a file, it'll just tell you when that file changes. If you give it a directory, it will tell you about directories in that file, files in that directory that change. Okay. So, what I can do is I can, to actually deal with detecting commits, if you know a little bit about git, the head moves, you update the ref log, okay, which is in git logs head. So, what I'm going to do is just tap, okay, the file system notifications, and we're going to say, oh, I commit. Okay. And what that will do is every time I do a git commit now, I'm actually moving my head around, it will come and just say this message. So, what do I want to do now? Well, what I can actually do is just tap that, okay, and instead of saying a message, what I'll do is I'll simply get the directory listing, and I'm using this .intercommit directory to keep my backups. And all I'm going to do in .intercommit is I'm just going to loop over the files and get them linked. Okay. And that just lets me get rid of those. So, that's how I can just toss the stuff, and I'm doing it just as I get notified. So, what about the files themselves? Well, let me just talk a little more about what this thing does. When I actually watch a path, I don't just get a list of file names. I actually get objects telling me the nature of the change, so I can see that here the path was awesome.p6, the event was a file change event. You can actually get renamed ones as well and things like that. So, what's going on in here is we're able to tap them and say, what we want to do is a little more interesting than that. So, one of the problems that you get into if you actually start doing this is that operating systems really suck at this. I mean, they're awful. On Windows, if I change a file once, I get two notifications. Why? Well, because some deep reason that I shouldn't have to care about, that's how they implemented it. These notifications arrive within 0.05 seconds of each other. It's really annoying. They just show up together. Now, of course, this is silly because I don't want to make two backups of the file just because the operating system thought that it should tell me twice about the same thing. How do we deal with this? Well, we can actually unique them. We saw this function on lists earlier. We can unique them by path. So, there's nothing new. Now, it turns out that because asynchronous things often have a notion of time involved, there's various extra options that we've put onto some of these various methods when you're dealing with a supply rather than a list. One of the ones that we have put on unique is actually expires. What expires will do is that it will basically give you a unique one once per that time unit, in this case, one second. So, if I get, say, I have two files and it's called foo and bar because we really imagined. So, I change foo and bar. I'm in my editor and I save all, so I save the two of them. So, they both get written out to disk. Now, windows being stupid tell me twice about each of them. But what will happen is the first foo will come in, we'll get into here, and what it will do is it will look at the path and it will say, oh, we haven't seen this in the last second. Okay, it spits it out. The second notification foo comes in and says, oh, we just saw that within the last second. No, I won't bother spitting that out again. Okay, but if we were to save it again, like five seconds later, it would say, oh, I forgot about the fact I already saw foo. So, I'll let it through. What you'll kind of note about that is that that's a not quite trivial thing to do. Now, there's something that makes this even less trivial, which is not necessarily very apparent, which is that IO notifications get shoved onto the thread pool. And what that means is that there's a whole bunch of threads that are happy to react to these different notifications. So, that's kind of nice in that we can make use of our shiny multi-core CPUs, which are getting more caused by the air. But it also means that there's a real risk that two notifications come in, two different threads are processing them, and what happens to the hash inside of here? It's not just that we manage to factor out state and flow control. In all of these things, very often, what we're also factoring out is synchronization, okay, and thread safety. We're taking it out of your code and basically solving a whole bunch of these things inside of these methods. Let's take a look at dealing with the actual backups. How do we do this? Well, for the backups, what we're going to do is we're going to watch the path. We've got a little bit more work to do. We're going to do the unique trick again, just to get rid of any due notifications. And then what I'm going to do is I'm actually just going to map the object and I'm just going to map out the path. That's the only piece that I care about. So I map out the path. Now I'm going to grab to make sure that they don't back up the backup directory because that would be really silly. Then I tap it, okay, and in here I've got a state variable. We just increment it. There's a very nice function called spurt, which is an inverse slur. Okay, it just shoves something out to a file. Spurt can, it was the least disgusting word we could find. Like spew is worse, spit is even worse. Spurt mostly works unless you, well, yeah, let's not go there. Anyway, the nice thing about spurting is that you can append, okay? So when you do that, basically it takes that file and just shows whatever you give it at the end of it. So that's perfect for us. We can write the change ID and the file name and we just do the copy of the file. Now if you're looking at this category you might actually come up with one concern based on what they told you, which is that multiple threads can basically be dealing with two of these notifications at once. And sometimes that's not a problem. This time it is because I have this little state variable here. I'm appending to this file. I don't want to get this all screwed up. So what I'm actually going to do is notice that I have this state. And when you're doing side effecting things and dot tack is not what you want. If you're actually going to do something where there's data involved that you're going to be competing over the potential of a friend and responding to the same kind of event, use act. This actually makes sure to do them one after the other. The act is actually meant to mind you of actor as in the actor pattern which might help you if you know what it is and won't help you at all if you don't. But basically what's going on here is it's making sure that we're only in this piece of code once at a time. So we back up the files one after the other and that solves that problem. So that's how we get to my back up program. Factoring wise all I did is I just actually created myself a class and put the two things into a pair of private methods. I also decided I wanted a log of what's going on. You saw that log. Let me just pull it up again. Okay, you saw that there. And that log is actually also a supply. What I've got in the main is an entry point of my program. Here's the main sub. This is how we tell it. This is how we tell it. We want to respond to watch being passed as an argument to the program. It's just a sanity check we're in a git directory. We make that directory. That's all boring. But here what I do is I make my new intercommit watcher and then I just take the log and I tap it. I pass say there and then the main thread is just going to sleep. It's going to be happening over in the threads. That's basically it. The whole program if we just go that's not the right file. It's doing dominance calculations. This is the class. You can see there's the overwatch. Down here there's the one I just showed you. There's actually these two other candidates for list and show. What they are telling the thing is that we only want to react to the list being passed. I did intercommit list, intercommit show and you can actually you might say where is that that nice usage message when I type that. The answer is it's generated automatically based on the main sub-routines that I wrote. There's just a side bit of shiny for you. That wasn't too bad but it was a bit of a compound because we only had one source of asynchronous data. We only had file notifications and I told you that we could deal with those in a nice way with this and we kind of did but I want to just step it up a bit for this final example and talk to you about what happens when we have some kind of asynchronous data and what I actually have in this case I'm going to have time and I'm actually going to do background computation on a fret. I have the idea of making this really silly application. It's a code golfer system. What happens is you type your code in here and then this little character count as you type and the more characters it tells you how long your golf is so you're trying to get the code as short as possible and that's code golfing trying to solve the problem in the few as possible characters. Of course I want to know how much time I've wasted in my life golfing this code so here is an relaxing number of seconds which I want to count every second. Now as I type this in suppose it takes like a second to actually figure the thing out. I don't want my user interface to freeze and I'm actually going to run this piece of code on a background fret and then just pop the results into this text box here. So that's quite a lot of things going on. There's three different sources of asynchronous data there's a user typing the stuff here there's these ticks from the timer and then we're going to have to deal with a fret asynchronously telling as it got done with the work we asked it to do. Now what I wanted to show you is I had a small problem and I realized on the way here that no one actually have done a GTK library in Palsox yet we got SDL and all of those so I had like an eight hour trade journey to get here so I actually wrote a GTK symbol on the way so it doesn't have all the control to it it does this one. So here is how we set the user interface up. I like simple APIs so there's not too much going on in here all I do is I make a new app that's the title of it and all I'm going to do is the way GTK works is that it basically uses these boxing things to lay things out that's a vertical box which means shove things one below the other so what I want to have is my source code tech box and then I want to have a label saying the number of characters I want to have a label for the amount of time that has elapsed and I want to have a text box where I will show the results of executing the code. So I'm just putting each of those into a variable because that gives me a nice way to refer to it later Here is how we deal with taking changes to the text box and updating that label. Now all events in this module I've written are exposed to supplies. Okay that means you can just tap the change event supply you can then set the text of that Charles label to say characters and we just grab the number of characters that are in the text box okay it's not bad so let's step it up a bit what about the elapsed time here we have to be careful and the reason we have to be careful is that here is my interval ticking away and the problem I've got with it of course is that this is running on the thread pool and if you update user interfaces from thread pools things get really really unhappy and then your application explodes very happy so what I basically have here is a little thing called a GTK simple scheduler. A scheduler is something where you give it a bit of work and it figures out somewhere to execute it the GTK simple scheduler basically takes a piece of work and hooks into the event loop of GTK and makes sure you run it on the user interface thread so the update is thread safe and it doesn't conflict with other user interface operations so the way we use that is we just take event source, intervals here we say schedule it on the GTK simple scheduler that basically takes this flow of seconds shoves them over onto the user interface thread and makes this update work out okay that's two pieces of functionality down, long to go so of course the stupid way to do it is whenever the text box changes okay we eval the code that sucks in two ways the first is the user is typing away and we don't want to eval the code for every single keystroke we want them just to hesitate for a moment and then we'll do it. The second thing is we don't want to do this on the UI thread because it will freeze the user interface so the first problem is solved using unchange unchange basically waits for the data to be stable for a time period then passes it along so if I keep typing, keep typing stop for a second on there and then it says okay now I'll pass it along so that lets me get a stable value okay another nice tricky problem that backs it away into one of these maps what about getting it done on a thread threads are dangerous and I mean you know how do we deal with this and you can sort of see the problem coming there's not just that we need to get the user interface update on that thread there's also the problem that what if the user types something we start evaluating it and then they type something else the second thing runs quicker as the problem we described earlier auto complete so we call start this is the way that we get a bit of work shoved off onto the thread point so we eval the code but this does something clever it gives me back not just a supply but a supply of other supplies now that's a bit of a headache when you first see it but let me show you why this is really nice we have something called migrate migrate moves its way between a set of different supplies so whenever a new one arrives it says this is my latest source of events it ignores all the previous ones and it therefore solves the problem so we're taking the text box we're saying let it even change for a second and start evaluating the code on a different thread migrate between the various different evaluations so we only ever care about the latest one schedule updating things on the UI, thread and doing a bit does it actually kill the older processes? they're not processes though they're threads so if you have a thread and you type sleep can you cover they're here to your problem what if it's holding a mutex things like that yeah exactly that's tricky we can talk about that after the talk because I'm out of time already I suspect but anyway in 29 lines of code we've handled UI events we've worked with time we've handled race conditions full threads that's the busy 29 lines of code it actually fits on one screen full on github this I don't really have time for but I just want to say in one word what two slides here have I didn't write a single line of C code all of this is done with native code including callbacks this is how I call the GTK signal thing so when it gets an event I toss it into a supply you can go and look at the code if you want to see more of that so let me wrap this up oh it says one minute oh wow that was three minutes ago oh wow go me so I handled asynchronous sleep so asynchronous things have traditionally been hard to deal with and I think that now reactive programming gives us a paradigm where we can deal with different sources of reactive data in a fairly nice way we can compose them together we can get a lot of complexity especially of timing and synchronization issues that kind of don't go away we can actually act them out of everyday users code get them into a bunch of these nice methods we have more than I have time to show you but really I the sort of philosophy here is asynchronous things easy you know getting a bit of stuff don't have a background thread and getting it back on the UI should not be too hard here I think we've made that a good bit easier the code is over there if you want to come and ask me afterwards that is how to find me or I'm around all day I would love to do questions but I'm out of time so find me at lunch or break or something like that thank you very very much