 So a few words about timing before we start. So next week is spring break, in case somebody didn't notice. PA7, the first stage of building your own browser, was assigned on Tuesday. And what you'll do in this stage is build a layout engine, essentially connect your parser generator to the parser, turn HTML, or a baby version of HTML into a DOM, and then using essentially attribute grammars to walk over the DOM and compute the layout, position elements on the screen, and render them. The other two projects PA8 and PA9, you will add scripting to actually modify the DOM and talk to the server. At the end, you'll have a browser more modern than most leveled runs on today's devices. It is 1,000 times smaller. It is also 1,000 times slower. But that's part of what makes it possible to build it in one semester in a class. Another thing I met with most of the groups already about their projects. The most important thing at this stage are the problems selected for the projects. And those are great. The next stage is actually flesh it out, figure out what the examples would be, what your language looks like, and come up with an implementation. Right after the spring break, you have to submit the revision of what you have proposed, essentially a design document. You want to think of it as a handout. As a handout in the sense of the handout that we give you for PA, for the various PAs. It describes the problem, describes examples, describes the implementation steps. Ideally, it should be so good that you can then pick it up and start implementing. Because you won't be able to quite flesh out everything since you haven't implemented it before, which is the case for us when we give you the handout. But it should really have the flavor of, I know what the language looks like. Here are a few examples. Here are the benchmarks. And here is my implementation strategy. So for most of you, you need to now start becoming much more concrete. And a good advice is to be driven by examples. So pick up a few scenarios that you would like to work on. Write your code for those. Make sure that at least one of them is impressive enough that you would like to demo it in front of the class at the end of the semester. And it better be fun enough that you actually have some enjoyment working on it. So with that, let's make sure I'm recording. So you'll start talking about even-driven programming, asynchronous programming, to some extent distributed programming. And that opens a new cans of worms that programming languages would like to clean up. And we won't cover everything today, but we'll do the first stage of this data flow way of handling asynchronous programming. So what we'll do today, we'll look at the first half of the paper called directing JavaScript with arrows. Essentially, it is about taking even-driven programming with callbacks and lifting it up to something like a pipeline. And then we look at Rx after the spring break and see how that differs from this solution and actually a baby version of Rx you will implement in PA9. So we want to take the typical handler code and turn it into something much cleaner to write, something reusable and composable. And here is the paper. It will be required reading. And I try to keep the lecture exactly like the paper so that you can go through the paper and lecture step by step and understand it. It will take some work, I think, to understand it because this is sort of one of the more advanced features of functional programming. And it will probably take a little bit of head scratching to understand it. So there are we now. This is the state of the art more or less of JavaScript programming. I wouldn't say state of the art in the sense of the best practice out there, but most of the JavaScript programs are written like this. You write yourself an event handler. It's a function that is involved when an event, for example, a click happens. That function receives an object which describes the event. And in that event, you're having a matter of things, the target. The target would be the DOM node on which the click happened. And the DOM node has some text content. This is the visible part that the browser actually visualizes on the screen. And as part of handling the event, you can change that content. So when you register that handler, it's here, it's registered by calling add event listener on the DOM node selected to get element by ID. So you register this handler for this event. When that event happens, you call this function which modifies the node. That's it. Now, it looks pretty simple. What are the problems with that? Can you guess how this simple thing which looks straightforward could get out of hand once the programs grow bigger? Continuous events? So continuous events would be events that fire very often or events that truly are continuous? Well, it would be a little bit hard to generalize. Without having to call some function like 100,000 times? Well, it cannot be seen of mouse movements as just events that happen very often, which in fact, this is how it's implemented. The mouse position is discretized. And depending how fast you move, you get a certain discretization of the position. The problem you have is that the mouse appears like a sequence of events, even though you would like to think of it as a continuous value, like an analog value, even though it is discreet actually underneath. Is that what you meant? OK, so we are not going to deal with that issue yet. That will come up later. But to clarify for others, essentially in any sort of distributed or even during programming, values are essentially of two different kinds. You have those events which are like messages. They arrive, you handle them, you can think of them as you consume that event, you consume that message, and it's gone. And these are sort of discrete events. The other family are continuous events. You can think of them as analog values. If you think of the current and voltage, these would be analog values. They always have some value which may slowly be changing. So what are examples of those in programming? Clearly, mouse positions are those, right? You cannot really, or you shouldn't really think of events you receive from the mouse motion as something that you consume and it's gone. The mouse always has x and y positions. What would be some other values in this GUI programming that should really be thought of as continuous? State of the element, like perhaps the value that you typed in into a form, OK? And also the color, and maybe when the document is scrolled in a particular position, then how far it is scrolled is also another value. That it's sort of continuous, always value rather than a message, OK? So that's excellent. We are not quite going to cover that, but we are working our way towards that. Some other things that are continuous rather than discrete, audio input, the time, right? The time should again not be thought of. You consume the time and there is no other time of the day until the next peak arrives. So good. So what other problems we have with events in addition to the fact that really logically we have continuous and discrete things in programming? If I can paraphrase you saying you cannot localize the logic with handlers into one code because often part of it needs to be in this handler here, part of it in some code that sets up the element. So the code is sort of distributed in not very logical ways across the code, OK? Related to that would be, aha, so the bubbling is the process that if you have a tree, you may have a node in the middle and you would like to make sure that when an event is, when say you click a leaf element of that, right? You would not like it to be triggered on all elements but only on that sort of root in the middle, on the parent of the subtree, right? Because you believe that that should be handler for the event rather than the leaves inside, OK? So when you click on an image in a paragraph, maybe the paragraph should handle the event rather than the image, OK? So you would like to have a better control about that. I'm not sure we'll have an answer to that. We'll see. Maybe there is something in Rx that handles that, OK? Other problems? There's other kind of event handler you have on fun. So essentially the nesting of event handlers within each other breaks the logic of the program but you don't really have a choice but to do it like that, exactly. So I'll have a simple example that illustrates this on the next slide but perhaps there are more issues. The one that this paper uses as a motivational example has not really been mentioned yet. The fact that we cannot easily reuse code, that you would like to write a piece of code and reuse it again and again and again and with event handlers you easily cannot, OK? So I'll show you an example next but maybe to summarize the discussion, if you realize where the computing world is going, the clients are going to be more interactive, right? More touch, right? More other sensors, shaking sensors on your head, your body sensors and so on. Everything will be much more interactive than it is now. The error of keyboard and the mouse is gone. There will be just much more interactivity between you and the device and you expect it to be much more responsive than it is today. On sort of the bigger scale, things will be more distributed because part of the program runs on the client, part of the server and that trend is not going to collapse back. Everything is going to be more distributed. So that means there is more asynchronic, more things happening concurrently and interrupting each other. Responses from the server coming in the middle of your client's computation, the touch coming in the middle of other computation on the client and they expect that the response will be instantaneous. So the world is going in the direction of asynchronic. The programming support is not ready for that. So in a sense we are now in the stage where normal programming languages were in sort of the 60s. When Dijkstra wrote this paper about go to considered harmful, I don't know if you were taught about this in 61B or wherever. Did they tell you about go to considered harmful? So in the era of before sort of structured programming which means you can have only if, then, else and by loops and these are nested in each other, people would just use go tos to say program will transition from here to here and Dijkstra said, well, it makes the program hard to read. Not only hard to read, you cannot easily compose it because you cannot take a piece of code and cut and paste it and stick it into middle of another piece of code because that go to may be missing its label if you just do it and that breaks composition. Whereas with if, then, else you can always cut and paste a piece of if, then, else and nested inside another if, then, else. So it is composable. You wouldn't even think today going back to go tos because you are so used to actually cut and paste a piece of code. That was not the practice then. Now, events are sort of where we are around that time, 50 years ago, except it's in the context of events and handlers and asynchronous and the solution isn't, of course, as simple as it was, don't use go tos because we don't easily have other good solutions. And what we are going to teach you is more or less just the proposal how it could be done. It's not clear where both languages will look like for asynchronous programming when the dust settles. But chances are they will look like what you will see today and you will see them for the rest of your life. Okay, so another use of events besides just registering events is to break long running computations into smaller tasks, essentially for the purpose of animation or doing things more slowly. So have a look at this code and try to understand what is going on. Something really weird, right? Let's take the best guess what it does. So if somebody's ready to explain it or take a stab at the explanation. Okay, so first of all, for those who don't see what's going on, the set timeout with zero essentially says when this handler stops, okay, what it says is register itself, right? And when would this handler itself be called? Well, in zero milliseconds. So as soon as possible. But the thing is that this handler will stop if we'll give control back to the scheduler and the scheduler could run other handlers if they are ready, if they are not and this will run immediately back. And strangely, the scroll top field of the element, which could be the document on the screen or just some sort of scroll box. We are shifting it here by one position, one pixel. And it would seem that it would always keep going and therefore this loop would always keep registering, right? But that's not quite the case. So there is some hidden nasty magic, right? So the semantics of this operation is, right? We are incrementing a field on a DOM node and the browser says, okay, I'll increment it. But eventually the browser says, now that would go over the top. You would be scrolling it too far and it will essentially not permit that operation. So that operation will have no effect. And this is when last and the value of scroll top would be the same and that the recursion effectively would terminate it. It's a little bit of a nasty way of implementing scrolling to the top, but not further, but that's what browser API does. Okay, so drag and drop is a really nice example, not too big, but yet showing the complexity used in the paper. So what does drag and drop does? It is sort of a canonical example of sort of stress test you could almost say of a framework for even driven programming. How easy it is to implement drag and drop. So what is drag and drop? The state machine describes the operation during drag and drop. You come to an object with a mouse. So here is your maybe file name. You come to it with a mouse. Now you click on that object with mouse down, then you drag it and then you release it. And here is where the object should stay. Presumably this is one directory and you are moving it to another directory with drag and drop. So on mouse down you come to a setup state of drag and drop. Then on mouse move events you keep dragging it. And then on mouse up you actually drop it. The object is on top of a directory where it can actually move. It will stay there, right? If not, presumably it somehow needs to fly back. If you do mouse up without actually dragging you cancel the operation right away. So what we are not going to talk about here is what actually happens in these states, right? For example the drop needs to check whether the object that you are dragging is in some target directory where the object can remain. We are not going to talk about that. But to understand the state machine it helps to think what would typically happen in setup, in cancel, and in drag. So let's go through it so that we understand the purpose of drag and drop and internalize it a little. So what would happen in setup? So setup happens when I come with the mouse on the object and click on it, right? So I have mouse down event on an object. What would you do? Would you change the appearance of that object maybe? Well, okay, so I want to distinguish now good. So you are going in the right direction. I want to distinguish between the control which is setting up the event handlers for move, drag, and drop, okay? Right, so this is the navigation through the state machine. And what we actually do in terms of the semantics of drag and drop, right? If I come to the setup state and I click on an object I may want to change its appearance. I may also want to do something else to prepare the operation in terms of the semantics of what I want to do with drag and drop. If it is moving files across directories then what may happen during setup? You may change its transparency. You may highlight it depending on the particular GUI. So that's in terms of sort of the look and feel. Semantically to prepare the operation of presumably move or copy, what do we perhaps do in setup? Okay, maybe you will wrap it into something else so that the GUI as you drag it it could actually visually be transparent, something along those lines. Now aside from visuals, what do we want to do in setup? Okay, so the way I would perhaps implement it in the setup, I would remember the source directory of the file. So that when I reach the drop I can say, okay, so I have a file in some target directory. I want to know where it came from so that now you can ask whether it's a copy, whether it's a move, whether it's legal and all that stuff. That's sort of the logic behind it. All of that, the appearance and the logic for the copying of files, they are completely ignoring because after all drag and drop can be used for many different purposes. Not just copying files can be used in a game. And so we want to design a drag and drop for our GUI in such a way that it could be used for anything you can think of. With slightly different visual appearance. So it really needs to be a reusable piece of code. Right, so we want drag and drop that looks different. Right, if I'm moving files, they may wanna become 50% transparent when I get to setup. When I'm moving files in a game, they may need to move to the front and give you a 3D pop-up appearance. All that needs to be parameterizable. So I want to have these codes to be reusable. What happens in drag, for example, that we are going to ignore here, but we need to be able to parameterize for it? We definitely, okay, we may wanna move the objects, but what about leaving some trail behind the object so that you can actually see where it's moving from, right? So the handler for drag may wanna leave a little trail that slowly disappears over time. That's another thing that the handler for drag may wanna do. What about the handler for cancel? The object is still in its original position, so there we perhaps just restore its original appearance. But what about drop? When we reach the destination, we realize we cannot copy the object somehow visually should pop back. So we probably need to issue another operation of not shown here for travel back, perhaps not instantaneously but slowly so that you can visualize how from the drag and drop it's flying back. You see the issue that arise in sort of modern, good-looking GUI programming? It's essentially coordination of things over time which is quite difficult in general. So this drag and drop is complicated enough to keep us motivated, but perhaps it's been simplified enough that too much and it will look too simple. But let's look at drag and drop in the typical implementation and try to extrapolate and see how things would look like if the program grows into something more fancy, a really modern GUI. So here is the handler for setup, receives the event as before the event has a target, so this is the element on which we click. Now we remove some listeners and we add some listeners and here is all the operation that we discussed we could do during setup, but we actually are not showing here because that really depends whether you are clicking on a file or on a tile or on something else. But why are we doing this? It's probably clear why we are registering these listeners, but why are we removing some listeners? So remember our state machine, from setup on mouse move we wanna go to drag state, on mouse up we want to cancel. So we clearly want to register this and that and we want to transition into these states, that's clear. But why are we removing the listener for mouse down? Is that necessary at all? Is it defensive programming? What is that? So the scenario you're describing is what if somehow two mouse downs happen? Then this piece of code would be executed twice and you're probably accounting on it to be executed once before cancellation. So it could break down your invariance in the data structure. Could it really happen that mouse down happens twice? Okay, but could it really, is there sort of a real reason that could happen? Let's see if, okay. So through bubbling they could get two events potentially. So it stopped the bubbling of the element to the other thing, okay. Are there reasons why we are canceling? Well, the mouse could be defective, but there really should be an operating system that sort of, even if the mouse is sort of glitchy, sends you mouse up before it sends you mouse down. I see, okay, that perhaps could happen. So if the program itself, you can definitely raise events yourself without raising them from the mouse. And now perhaps this is one more reason for defensive programming. What if another programmer decides to later do the animation under sort of program control rather than user control and then she will send two mouse down events and you have a problem. What about this? What if the state machine actually look different? What if here being, maybe this way here. What if I have mouse down? So I have a state machine where mouse down could do two transitions, right? It could do this transition and that transition. So two different parts of the state machine listen to the same event. Presumably on the same target, right? That seems like a good reason also to cancel this transition because sometimes down the road you may need to listen to mouse down again and make the transition over there. So whether it's defensive or truly needed for state machines that could have mouse down on various places, it's a good idea to just say, I'm going to cancel. Now, presumably sometimes later we need to restore it again because the drag and drop could start again. Okay, so here is the drag event, essentially the same story. Cancel this, right? But we add it again. Why? Because, okay, why are we doing this? Why are we canceling the first one in this case? I'll switch to the state machine for a second. So we are now in this handler. So the first one here, we are canceling because here we were waiting for this event or that event. This one actually took place. This one didn't, right? So we are canceling the one that we were waiting for, okay? And now we are getting ready the mouse up to transitions into here because now we have moved and now if the mouse up happens we are not going to cancel, we are going to drop, right? So what we have done here is cancel this one and establish that one. So we are sort of building that state machine on the fly. And we kept the mouse move because if mouse move happens again we want to stay in this state, right? This is what we do here. And here again is the logic which potentially draws the trail and so on, okay? Here is the drop which again removes listeners. All of them be at the end of the state machine and performs the logic here and the cancel event is similar. And now this is how you set it up. You take the drag target which could be say all the files actually in your system and you say on mouse down we wanna get to set up and this is what starts this drag and drop. So if you look now at this code why is it not easily reusable? You would like to take the sequence of handlers. It's not a big state machine, only four states could be much bigger. So pretend it's bigger pretend you don't wanna write it again instead you would like to take this piece of code and use it in another setting for drag and drop of some other things. Could you just reuse this code, okay? So here we have the code hard coded so we cannot really reuse it for handling of other things. There must be a solution for that problem, okay? But that should not be a problem assuming that we are not dragging the same element at the same time, right? Because we are removing the handlers from only that element which is being dragged. Oh, after the drag and drop. I see so if you want to extend the state machine to some, right. Yeah, so growing the state machine is not clear how you would do it, right? I think that cannot be done. The fact that this piece of code, the logic what actually happens when you drop that may depend on whether you are dropping a file or a tile, we could generalize this piece of code to actually be parametrizable that way. How would you do it? Okay, so the idea is to somehow add here another argument which would be a function and that function, call it f. That function f would be called here and that function would do dropping of a file versus dropping of some other things. Okay, so that's fine but how do we actually pass that function into this handler? You need to sort of find a way to compose the state machine in such a way that function can be passed around. So there is a common trick which I'll show you in a few slides used in these event frameworks. So that it could keep one state machine but the behavior would depend on what it would click on. Click on a file, the drag and drop looks and logic would be different than when you click on say a computer that you are dragging somewhere. So how could we do that? Exactly, so the answer is rather than passing the target directly, say the dom node, you wrap it in an object called a proxy and the proxy will carry with itself a function like this and then at this point here you invoke that proxy and now we have a state machine which is reusable at least in the sense that we can drag and drop things that should behave differently than we are drag and dropping. We still cannot compose the state machines either. So there will be an example of, we talked about that, okay. So there will be an example of a proxy coming soon but at least one part of the composability we have solved with the proxy. So these arrowlets are sort of operators for composing event handlers into state machines, state machines that you can sort of concatenate like regular expressions one after another or in parallel and here is how their program would look like for drag and drop. The fact that things are dotted here means that you can write this separately from the rest then compose it as a standalone unit with these operations to create a bigger state machine and then compose it with that. Try to have a look at the state machine here and it is pretty much what we had before but there is something funny in it. I wonder if you can identify sort of semantic twist that we have done. So what is different here in this state machine from the one that we had before? So I think the fact that we have duplicated this drag node is one thing and that's fine, that could probably be avoided with a little bit of rewriting but there is sort of one more significant change that it seems like we have many more nodes, right? But here we have one node and another node whereas before in the state machine we had a state machine that is sort of the usual one we use for regular expression that we did have states and we did have labeled transitions and the transitions were labeled with events and this is when you did make a transition. Now look how we are representing it. Everything is a node. So we have two kinds of nodes, ones that essentially wait here and block until the event happens and if that does it goes down the pipeline and then there are the others that really just represent the state. But that's fine. As long as we know that some nodes are sort of asynchronous and blocking and if they even comes they continue executing whatever is the rest left down the pipeline. So let's look at the semantics of this. So clearly here is the part of the state where we are trying to finish the computation so we are returning some special value from this pipeline called done. Here we are returning a special value repeat and depending on that this repeat will either happen or not. So these are sort of loop exit values, okay? Here are our original states. Here are the transitions on events and here is a composition which says you are waiting for either this event or that event to happen. And together this builds a sub state machine that either drags or drops. Is this part here? Either repeat or you drop. So this is what we have built here. Here is the one that you either enter the drag state or you cancel. And here is the setup. Say a mouse down we actually enter the setup and then you compose it with the rest. So this is how the programmer would like to think about it and compose things together. How would you actually write it in a programming language? Now we need a syntax that will actually encode that. So can you suggest how we'll stick it all together? If I let you design your own parser then of course you can almost literally transcribe this into a graph, right, you give these some names. This could be drag A1, drag A2 and then arrows will make transitions to those nodes. But if we say let's stick to the syntax of JavaScript, how would that look like? How would you design the syntax of that? So you are mapping events to functions, right? So here we would be mapping this event to say that function and the function perhaps corresponds to the rest of the computation. Okay, how about the fact that the mouse move can happen in several places. What would be moving? Map it to. You know, in the previous sort of non-composable way you would sort of deregister the handler and later at runtime you would register it. It would sort of be a little bit of a mess to program. And it looks like if you have a dictionary you would be in a similar kind of trouble. So how could we compose the state machine together? So here is their proposal. Let's start from sort of the very end. Imagine that you already have this part of the computation, the big one, the drag, drop, or cancel return, okay? So this is how you set up the entire program. Let's look here. So you create a special event object. It's called an event arrow, hence this A here. But you can just ignore this A for a second. So this creates a special object corresponding to the beginning here of this pipeline. You can think of it as that when mouse is clicked down this object is created, okay? Now you bind it to something. What is setup A? It's a handler. It's a handler that performs this word here. Actually, I made a mistake here. So this corresponds to that. And now what happens next is the computation in here, right? This box. Now what we have defined, we have defined drag and drop A, which is this entire thing. Now it's the entire state machine. Now all we need to do is run it. And the way we run it is that you create an element. This is its DOM name. We attach to it this program and run it. It doesn't mean that the drag and drop happens. During the run, the handler essentially gets registered. So what you see here are two operators. For now, we can assume that they are the same. Bind and next. And what they do, they take one part of the computation and they stick it to the rest of the computation and then there is another one here, okay? And you can build bigger pieces out of smaller pieces. Now you have composed this program. You attach it to the element and then you say, now really put it all together. So at run, the handlers get registered so that when the events happen, they actually propagate the way they should. So the composability of this should be clear. The only thing is the nasty difference between bind and next. So if you had only next, everything would be clear. We are sticking things together. But there is bind that differs from next in some subtle way. And it guess as to what bind does. That's different from next. So in that sense, both of them are the same that they are non-blocking. Bind has this extra feature that it sends to this callback, right? Because what are the setup A? The setup A is a program like this one. Anything that ends with A is a piece of program that you can glue together into this pipeline. But the bind calls it. It also sends this object on which we clicked. So it gets one extra argument. It gets past this object so that it can actually operate on it, highlight it, register something with it, change its position on the screen and so on. We'll see it soon, but for now you can think of it as being the same as next and that's essentially something that sticks objects together. This one here, let's have a look how this one is created. This one is sort of easy because it only says, let's build this one and that one and then glue them together with an OR. So it says, takes this node which waits for mouse move, composes with drag A, composes with this program here. The other side waits for mouse up and binds it with cancel A, which is this. And then these two parts are glued together with OR. Here is the operator that takes one program and creates a composition of the other and essentially takes this and that and creates the one big thing. So now you can see how programs can be glued together regardless of how big they are inside. So how about this one? This one is a little bit trickier because we have a repeat loop here which needs to terminate at this point. So inside here we compose mouse move with drag A and then in this case we sort of return repeat and in the other case we wait for mouse up, do drop A and then do done. And here is a repeat which is this loop all around this and this will repeat it inside as many times as necessary, right? Each time we go through this branch we need to repeat the inside state machine. Now you see the entire data flow language for composing those events together. So you see now how this language can be built. Oh, there is this one other thing, there is the proxy, right? See now the handlers that we call drag A, drop A. This is where the entire work happens. These are the handlers that we call from here, from here, from here. Also set up A. Now they contain the proxy, so the object, the DOM element is not wrapped, is not passed directly itself, it's wrapped in an object, okay? So DOM element is wrapped in a proxy and the proxy object contains these four functions, each one is this here. So depending on whether you have clicked on a file or on something else, you wrap it in a different proxy with a different setup drag and a different visual appearance, different logic happens when you're calling setup because the proxy will involve a different setup drag with itself. And then the proxy is passed around down the pipeline so that it goes with the object down as the events propagate. Now to see how you can reuse it, so look at the program that we have built, here is drag drop, okay? Now we can start it not only on mouse down but also on mouse over, right? So now you are composing the target with an event, right? We are waiting now for mouse over before we start drag and drop, but the rest is the same. And here is a jigsaw puzzle, so let's see if we can read what happens in this jigsaw puzzle that also does drag and drop. Imagine that you come to a piece in the puzzle and you are moving in from sort of a pile of the pieces down to the right place where you think it belongs. So is the program now so readable that it's actually worth it to understand the language and program we did rather than with a bunch of callbacks? Can we decode the meaning of the program? So what do you think this function does? Or is it a function? You really need to think of it because it is an A, it's an arrow, it's one of those things that are connected in our pipeline. So let's try to write this pipeline. So what do your next piece do? Or when does it execute? And you guess as to what is the purpose of next piece? Presumably next piece is something that we could plug in and it could have one behavior or another, so there isn't a single answer to it, but it does have certain interface that we expect in this composition. So if you look here where we composed waiting for a mouse over and then we did the setup and then drag or cancel, what do we have at the beginning? It takes a target, some DOM node, the Rhapsody in a proxy and then it registers on it the entire rest of the pipeline. So what will happen here? What do you think next piece will do? Okay, so presumably the game has a bunch of pieces that need to be played and there is some component of the game that gives the player the next piece more which the player can come with the mouse, presumably do a click, right? And then at the click the setup happens and the rest of the drag and drop. So next piece is something that registers the next piece that can be played, but presumably some other component just displayed on the screen. So this is actually, right, the element to be played. It's of course a DOM node wrapped in a proxy. Now what happens next? We connect it to an event click which means we are waiting for that click, okay? What do we do next? When you click the setup happens, so we highlight it in some way, perhaps pop it up to give you a 3D impression, then happens what? We do drag or drop, okay? This is the first part of the state machine and now we modify a little bit the rest of the state machine, the one that was looking for illegal drops. So what do you think happens here? So what do you think this program here does? It can return one of two things, either done or repeat. When does it return done? Well, it's a different state machine slightly now, right? Before what we had, you cancel only when, well, what does it repeat? It repeats this, right? It does repeat, it repeats drag or drop. So it repeats, right? So it has drag or drop, okay? To which we have composed something, right? So there is the drag or drop which we have built before. There is our drag node and here is, what is here? It looks like this, right? Essentially, we have implemented this state machine in drag or drop. Now we are concatenating to it this repeat if wrong and depending on the outcome, we go here or we are done, okay? So here is an example of a composition where we did build before a state machine that waited for the events and did the right transition and now we say, well, maybe it needs to be repeated if it dropped it in an illegal place. Well, I see, so you're saying that you dropped it and now we are going to continue dragging it without setup. So, okay, perhaps in this particular composition, it makes sense that when you drop it without actually placing it into a legal location, it still remains highlighted and you don't need to set it up again. But that's a good point. Perhaps the repeat indeed should go all the way here and restart everything. And in fact, having a language in which you can composite at the high level would allow you easily to change it rather than going back into the states and set up the transitions to go into the appropriate states which are distributed like spaghetti across the whole code. So whether this is correct or not, it is easy to change. So I want to quickly look at the combinators that are here. We'll go through their implementation partly today, partly after the spring break. But a few things that you want to highlight is you take a function and you lift it. What does lifting mean? That you know what the function is. Lifting it means when you turn it into some object that you can now stick together with the next operators like before, essentially like pipelines. And now once it is lifted, you can do the following things. You can do F next G as we did before. And essentially what it does, it composes these functions like that. A product creates a pair, but maybe what we should look at is the OR which we saw before the repeat. Just essentially wraps those arrows, those blocks with transitions like with regular expressions except we are not using regular expressions here. We are passing events potentially waiting for them. And here we see the difference between next and bind. The difference is that F bind G is going to call F on its input. And then it passes X the original input together with F of X to H. Oh, sorry, to G. So it passes that original proxy so that G which we are binding to F has access to the proxy and can draw and render it the right way. Otherwise it behaves exactly like next except there is this additional X passed here. Okay, so how do we implement it? So arrows are these ideas for composing these pipelines essentially lifting the idea of composing regular expression to the world where you're waiting for events and don't have to make the transitions synchronously as we did in the regular expressions where we always made a transition after reading a character. And so what is an arrow? It is essentially an object composable. It only needs to have two operations. One is that lifting operation where you take a function and you lift it up into an arrow. And it needs to have this next operation which takes two arrows and glues them together into a bigger arrow. That's essentially all we need. And then you can have the additional ones such as repeat and or, but these are the two crucial ones. I can skip that because it's not crucial but how do we do them in JavaScript? So there is something strange going on. Is there somebody who speaks JavaScript enough to explain what is going on here? Sort of the horrible abuse of good sense and good taste as well I would say but this is how JavaScript decided to handle functions and we'll sort of play along today and use it for a good purpose. So what's going on here? Okay, so let's not look at the body here. What it is the body here relates to our way of defining arrows but just this first line here seems a bit strange, right? So you're saying that all functions receive a method. That already doesn't seem to make sense because how can a function receive a method? It is kind of inheritance or the prototype based inheritance, right? It is the idea of prototype based object orientation inheritance is the same in Lua and self and JavaScript except there is something funny here is that what is this here, right? Presumably it is an object that has a prototype which is the same as the meta table in Lua, you could say. And now in this prototype we are going to set a special field A and its value will be a lambda, okay? But how can function have a method that is that thing that bothers me, right? Or even we can actually simplify what you said further and say that in JavaScript functions are objects too and therefore they can have fields, essentially keys to which you can assign values. And because they can have fields they can have also the prototype field, all right? Which leads presumably to an object that is the prototype of the function. And now you can say, okay, this is the object function. Essentially all functions in JavaScript are not just closures, they are inheriting from this object function. It has a prototype object to which we add A, this is, I should use A, this is our lifting operator, okay? And we will give it this function. So now we are saying the function now is going to be liftable from a plain function into this arrow that we can then stick together. It really bothered me for a long time but somehow I grew to accept it that functions are object too. Now, let's look at this, let's look at the other one. So we'll give it now the next operator. So now a function is going to be an arrow, why? Because it is an object that supports these two operations that we need the one to lift the function up to the arrow and then next to compose it together. So let's see how this will work. I should call it next, but in Haskell they are called array and the arrow. So look at the second function. F would be the receiver of the next message, right? So if I have a function foo and I call next on it and I pass a function bar, then this would be function foo. Now what we are going to do is lift G even though clearly this is just an identity function. So let's discuss it in a second and now we are going to return what? We are going to return a composition of F and G exactly as planned and it is going to be a function. So the first question is, is this implementation indeed as we planned, are we composing two functions together in the usual function composition sense? Apparently yes, right? We take the receiver and we take the G which is the argument of next and we compose them together and return a new function. So how about this call here? Why are we doing this? When A does nothing but returns it back to us. So what's the reason for that? What is meant by this comment here? What does this refer to? Well, imagine you define a function foo whatever and now I say foo next. Well, I could compose it with itself, why not? So foo is in law just a closure, you couldn't do this, right? But in JavaScript foo is also an object. So you are going to look up the function object and you will try to find the field next. It doesn't have it directly in this object here because we did not add it but through prototype it will find it in the sort of master function object. This is the one that we added here and this function is going to be called at this point, right? So this is exactly as object orientation in law except functions are objects too. So we can do a dot call on a function. Now this is going to be the receiver of this object-oriented call. So this foo is going to be bound into this. And so when I make a call foo dot next, here I extract f and g, these are now the two functions that I want to compose together, right? So when I do foo dot next foo, these are the two functions that I want to compose together, inside next they become f and g. But why this call? If I removed it, at least on these examples, nothing would change, it would work just fine. So if it didn't have the method big a, then it would just crash, right? So presumably we don't want to, if we wanted to do error checking, we should really do it the right way. Check for presence of the method and return an error. So when would that be useful? I want to do an error. Exactly. So we may want to do something like, how about one dot next dot foo? Now I don't know whether in JavaScript we can actually add a next field to the int class. Perhaps you can, okay. Then this would be legal. So we are composing now one with foo. One is clearly not a function. Could we define a reasonable meaning to lift it up into something that is composable, right? So we have a foo. It's a function that whatever value comes here, foo will transform into foo of x. But now I want to compose here before foo of one. What would be a reasonable meaning for foo? It could be a sort of nullary function with zero arguments, always returns one, a constant function. So it seems perfectly reasonable to lift a constant into a function. But this lifting operation is not going to do it for us, right? Because that one is called only on the receivers that are functions, not integers. But if I pass here, something like foo dot next one, then g is going to be bound to one. And now here we are going to call one dot a, right? So but if ins have an a function, we leave them into a function that's composable with a regular function, we are fine. Well, to make the first version work, right? So this one, we need to have sort of the next field in the integer class, right? And that there would be some sort of analog of this function in the int class. And that inside would probably lift it into a function. Here we don't have to do it because we know here that the receiver here is already a function. Otherwise we would not end up in this place to begin with. So let's see how we would use it. So here is a function that adds x plus one. Now we can compose it with itself. We get another function, which is also an arrow because we have defined for it the lifting and the composition operator. So add two, we could also compose with add one or add two. Now when you run it, it returns three, okay? There is no magic here. So this is clearly just an explanation of what arrows are and how you can compose them into pipelines. Let's make it more interesting now. The functions that we have composed so far, you know, we could compose whatever functions we wanted. They would not really work for asynchronous compositions. Imagine you want to compose two pieces of the pipeline such that both of them are waiting for an event. Imagine you want to compose click with some sort of move. And now when you compose these two, these are functions that are waiting inside, where they would be waiting inside this wrapper. Why is that a problem? So let me ask this again. So imagine that we use this style of composition of functions, which is really simple. We take one function and other one, wrap them in this and this is our new composed function. What can go wrong with this composition? Well, perhaps we could compose differently depending on whether we are composing. So the arrows could be functions or other things, but I see, we'd rather not do it. We'd rather have, when we're composing a constant with a function, the way to really do it is to lift that number into a function so that after lifting everything is the same and the composition operators are simple. They assume you are composing just functions. Perhaps things could get simpler that way, but there is sort of a fundamental problem here when we are starting to talk about asynchronous things. So let me give you a hint. So what we are returning here is a function that composes two things. Some of those things here, for example, F could be a handler for an event. So it should be called only when an event happens. So if you look back at this example, imagine you want to compose together, you want to create this program. What does this program do? It waits for a click, then it waits for a move, and then it happily goes down the pipeline. Now I would like to take the handler for the click and the handler for the move and compose them like that. I cannot quite do it, right? Somewhere inside I need to set up a mechanism where I will wait for the event, then I call the handler, and then when that handler is done, I'm gonna wait for the second event to arrive. So I need a mechanism where I call a handler for one event, say click, it does whatever it wants to do, and then I finish it, and then I wait for the next event to arrive. I call the other handler, then it's finished, I wait. So you see a problem with this composition here. Could they be defining in such a way that they wait for an event to happen? Well, can they, that would, okay, so you are getting close to it. So what is the problem of composing this way functions that are supposed to wait for a handler? Sorry, wait for an event to happen, and only when that event happens they continue. So let me, let's try to write it this way. So you have a function F that is a handler for one event, then you have a G that is a handler for another event. You call G, that calls F, and then F returns back to here, to the call, but you really want to make this call here only on event. And now in the middle of the composition of F and G somewhere in the middle of the code, you are forced to block. Looks like you would like to take a yield and say, go do something else and return to this point when the event happens, right? You could do it with coroutines and say yield here, I'm suspended in my state when the event happens, come back here. But JavaScript as we saw does not have any such mechanism, right? What does JavaScript do when it gets an event? It calls the handler, the handler must finish before anything else can happen, right? That's a serious restriction. So we need to set it up in such a way that when something is waiting for an event, we are waiting for the event, we call that handler, start at the beginning of the handler, go all the way to the end, then we return back to the dispatcher, to the scheduler of the JavaScript program and wait for the next event. If we compose these handlers like this, we are forced to make a transition back to the scheduler in the middle of the execution, like with yield, with coroutines, which we don't. We need to therefore set it up completely differently. So what would be the right solution? You could add coroutines to presumably to JavaScript, we're not gonna do that. So exactly, so we'll set up functions in such a way that they are not going to return. When they are done, they are going to call a so-called continuation of the program. So here is the continuation passing style. CPS function is essentially a function like any other, except it doesn't return. It doesn't return its return value back to the caller. It does something very different. What does it do? Well, in normal program, you would write g of one, you call g, g returns with its return value and then you do plus two on it. Now, if you wanted to write it in a continuation passing style, what does it mean that you are passing into a function, a continuation of the program, look what you would do. You would call g with one as before, but you give it the extra function and this function here represents what? It represents the rest of the program. There's really the rest of the computation. And look how we have rewritten g before g had the computation which was returned back to the caller. And here we do the same computation, but we are not returning it. We are passing it into the continuation. It's a pretty deep theory in computer science about computing with continuation, partly because when does the continuation, when does a program in the CPS style, when does it return? We have decided that every function is not going to return its value. Instead, we'll give it a function that it will call with its return value. So things will be just calling each other forever. I see this puzzle man here. It looks like this is a problem. In fact, it is a solution to many problems. So it looks like continuations will keep calling each other. Fine. Yeah? Well, if you apply a Taylor recursion optimization, then what problem do you solve? So first of all, it is true that program in the CPS style is never going to return because it doesn't return. When you wanna return, you are forced to pass the value to another function that you call. But that function is always a tail function, right? You call it and nothing will happen after it returns because, well, it doesn't return. So nothing can happen after it returns. And so you can apply the tail optimization which is you don't really push anything on the stack. You just reuse the current frame on the stack because you will never come back to it. So turning program into a CPS style would be, by the way, our solution to implementing coroutines. Remember, we introduced bytecode so that we would not have a call stack but instead had always sort of flat stack. We could have instead converted into CPS style. And by the way, there is really simple isomorphism between the bytecode and CPS style. This here value that we are passing here, you can liken it to the temporary variable that we introduced in the bytecode. And so the CPS will come handy here when these handlers will call each other at the end when they are done. So we'll introduce next CPS arrow so we'll compose functions in CPS style into these pipelines. And then on top of it, we'll start doing events. But that will happen after the spring break. Okay, thank you.