 conference, and it's a great conference, so happy. So this is yet another how to rank better code type of talk. We're always helping each other out. I assume everyone here knows the topic based on the schedule. I'm not gonna cover all of React and Cocoa, that made me way too hard in the half an hour, but hopefully this will allow people to get started, or at least give something to frame your learning going forward. So we're gonna dive right in. We're gonna look at some code. So what I'm gonna do here is just throw some code up on the screen that shows how you might, using React and Cocoa, go touch a limit, touch a button that is to take a picture, or select a picture from your photo album, and process it with a filter, maybe upload it to an API, and then update your UI with the table view to show the new image, in like a messaging app, for example. So we've got some photo button somewhere, and then we've got this awesome name method. So just think of this rack as a software, just ignore it, it's in Objective-C, prefixing is pretty common, but the main part there is signal or control events. So normally when you'd want to react to something that a button does, or now tap on a button, you would register using target action. Here, we're creating something called a signal, and we're gonna work with that. What's a signal? For now, just think of it as a real-time array, so it's just something that keeps going. We're gonna map on it, just like we would with an array. I apologize for using the exclamation point. That's kind of, it's not actually like what you would use bang for in Ruby, but it's kind of a necessity, because in React Cocoa, the map method takes an explicit block parameter, not the implicit one that we use in Ruby. So this allows us to not use a lambda syntax, give us the more normal syntax. So we've got the button tap, that passes along an event. We map the event into an action sheet. So we create the action sheet with some title and two options, select from the camera, like take a picture from the camera, or select from your photo album. Do next, this is like each basically, and you could do an alias if you want. So we map it, now for each one, we're going to show it. Now we're, here's where we get into some a little bit more complicated React Cocoa. So we have an action sheet, that action sheet would normally use a delegate. Here we have a signal that sends values, just like the button tapped it up above, whenever you select one of the icons on the action sheet. It's just going to send the index of the button you clicked. So the next line is ignore, and we're going to ignore the button that's at the canceling next. Finally, we're going to map that from the button index to a source type. So we're going to be using an image picker controller, and the image picker controller has a source type. I'm really sorry to interrupt. Can you give me like two sentences that can relate to what React Cocoa is? Yeah, I'm going to get into that. Yeah, sorry. So this is my awesome attempt at doing like the called opening in an OV, where you just like get into the action menu so yes, so we'll get in there right now. So yeah, so we take the button click signal, we ignore the cancel button, because we don't want to do anything when they cancel, and then we map that to an image type for the image picker, whether it's from the camera or from the photo mode. Now, what we've done here is we've mapped some object into a signal. This is a signal signal signal. It's compositional, like it's closed in the mathematical sense. Everything here is returning signal. So now, instead of a signal action sheet at the end here, we have a signal of signals. We don't want them, so we throw in a flat one. We'll get into flat one a little bit more. So now we map the source type into an image picker, pretty straightforward. Now, we have an image picker. We want to show the image picker. We want to get the selected image from the image picker and then dismiss it. So concat is to sequence things in order. So we present it, once it's presented, we start getting the, like basically waiting for a selected image. I've got take last on the end. That allows the image picker to stay open if you're selecting from the camera roll, and maybe mistakenly press one and not the other. Anyway, so that's sequencing. Again, we're mapping to a signal. So we flat one. Now we have the image info that comes back from that signal, which is just the dictionary. So we get out the image and now let's just assume we've got some variable somewhere that's a filter. We're gonna apply that filter to the image, like Instagram, and this thing can take time. Filtering the image, we don't want to wait on the main thread while it does that. So that's a signal. And we're going to subscribe on and that's not a scheduling thing. It's basically just like a dispatch queue. So we're creating a background dispatch queue and you can set different priorities. And so this work will get done on a background queue. Now here, instead of flattening, we do concat. And that's, we saw concat used up above. Same thing here. We don't want to do this. We want to do it in order. So one at a time. The work is done. We've processed the image and we now want to go back to the main thread. So there was a, oh, I went to slide score. So basically now that we've filtered the image, we're going to use our API to upload the image. This is also asynchronous. We also want this to happen one at a time. We don't want messages, photo messages to be sent out of order. So we concat it, concat it. Finally, we're done. And we want to update the user interface. So deliver on is the opposite of subscribe on. And that basically allows us to put the result into, deliver it on the main thread. The most important piece here to notice here is to subscribe next slide. Everything we did before was late. Nothing actually happened. We were setting things up. It's almost like there's compile time and there's run time. This is signal setup time if you will. So nothing happens until something wants to happen. So you have to subscribe. Once we subscribe, we open up the gates and button tabs go through. Action sheets go through. Image pickers all the way down. So we have an image. It should be image, not image input. We create an image message. We apply it to our array that we've got kicking around. And we insert it at the index path that we wanted to have. So the reason for going through this way is I wanted to give you a sense of how reactive local works or things go sort of in a top down compositional manner. And it's almost like writing really command line scripts. Everything can read top down. You don't have to worry about setting up target action callbacks or delegate callbacks and see where the code goes elsewhere. So you might not do it exactly like this. You might use, you'll still use functions and methods and other objects to do things. But for control flow, for data flow, for interaction flow, that's where we have to go cook and shine. So now we get to the title. Reactive Ruby Motion. I'm Dave Lee. I'm the React Cocoa contributor. And on GitHub and Twitter, my username is castaleo. So just to sort of review what we talked about there, if you say composition in object-oriented programming, it's usually some object has some other object in it. It calls through to it and takes values back. So this is kind of just a rough idea where you've got objects that pass things around and do different things. But there's no clear start and end. Things are just sort of like this piece of stuff. And you can do it nicely. But in React Cocoa, we compose this way. Each of these represents some sort of computation. Do this, do that, do that. Computations don't have to be linear. You can have two items feed into one thing. So philosophy on this talk, I gave some examples. React Cocoa is pretty big, so I'm going to keep the scope pretty narrow. I'm going to try to keep it familiar so everybody understands. React Cocoa, because there's a lot of terminology for React Cocoa. That can be stolen in blocks to learn. I know myself. You go to the GitHub repo and read the readme and read some documentation. There's this laundry list of things you kind of need to know. And it's not easy to read it all. And so, yeah, I want to try to address some of the common areas where people have hurdles when they're learning React Cocoa. So when people try to teach React Cocoa, there's often narratives, like, you know, like mutable states and other things. I'm not going to really do narratives. There's functional programming. I'm not going to talk about functional programming. And sometimes people say, oh, you really should do it this way. I'm just going to show you and hope it catches people's interest and those who are interested don't feel better about it after this talk. So I mentioned there's a lot of things in React Cocoa. We're not going to use those. We're just going to talk about one React signal. So as I've been alluding to in these previous slides, there's a lot of terminology in React Cocoa. Not only are there those classes, but there's a lot of operators, things you do to signals. Don't get caught up on it. I think Cocoa has a way bigger vocabulary than React Cocoa. To be a Cocoa developer and use Apple's documentation, you need to know more concepts. OK, so we're going to figure out signals by refactoring callbacks. So let's take a look at types of callbacks we do in Ruby and in Objective-C. There's blocks. There's what I call an object string, which could be a target action, could be KBO, could be notifications. You give some string or some selector and say, tell me when this thing happened on this object. Delegates, kind of similar, but there's an API involved. And even subclass, right? Like, a subclass UI view to get told when the view has certain lifecycle events. Callbacks can have different purposes. You can iterate over them, just like mapping or doing anything on your way. There's asynchronous results. Sometimes an API is going to take some time. It's going to do something that you don't want to wait around for. Maybe you want the results of it, a value. Maybe you just want to know what it's done so you can order things appropriately. Errors, callbacks can be used for errors as well. Events, so another callback is, hey, this thing happened. There's not really a value. It's more of a semantic touch happen, the app change state. So here's an example of a hypothetical callback on a networking client. You see it get some path with some parameters. You've got a success block, failure block. But really, there's kind of three callbacks here. Because when you call this the first time, or when you call this inline, it has a return value. Return value might be null or void or whatever. But there's still three ways out of this app, this line, into this one, into this one, and then back up. It's hard to reason about that. There's a lot of ways this can go. And once you start nesting things, we don't know what callback help is. There's ways around it, but we know it's a problem. So callbacks have a few different dimensions, the timing and the type. So timing is whether it's synchronous or asynchronous. And the type is, callback might be for values, might be for errors, might be to let you know what it's done. So let's try to refactor to a brand unified callback. So there's this quote, some of you might have known it. All problems with computer science can be solved by another level of indirection. So that's what we're gonna do. So instead of all the callbacks we do, you sort of pass something in. You say, here's my object, here's a string or a selector, here's a block. So instead of passing the callback in, we're going to return a callback object to the callback. So our last API call would just look like this. If you want a value, you could say callback.each. Do something when it gives you a value or more than one value. Failure, maybe you do something like that. When it's done, something like that. And maybe you have to do something like that because you need to handle all of that. So what are the benefits to refactoring this way? Consistency, it would be nice to not have to know all these different ways of doing the different callbacks and having to try to move them all together. Oh, sorry, responsibility. Now that we have a callback object, maybe refactored for SRP, you can say, let this callback do certain things for us instead of putting that callback in line into our callback method. Sorry for the mumbo-jumbo here, dimensionally agnostic. That just means when I talk about the dimensions, whether it's async or synchronous or whether it's errors or values, this callback, the end is all of those cases. So it doesn't really matter what you need a callback for, this covers all of them. An abstraction, now we have signals that give us an abstraction that didn't really exist before. Let's try to do something. So obviously at this point, I have to jump into a crack signal. So that callback that I described, that's what crack signal is. So instead of passing in blocks, et cetera, your method returns a crack signal. This is basically like a super return. It's a return that you can do something with right away or you can wait on it. Code looks kind of the same. Some of you are probably familiar with promises, so it's good to compare and contrast. Promises are typically a single value, so they're good for network requests, like fetch something and give it to me. Signals can have any number of values, it could be zero, one or many. Promises are eager, signals are lazy. I mentioned at the beginning that there was that setup that I did and nothing happened until the subscribe. So as you set up a signal that doesn't do anything until you need it to do something, which might be good for optimization, don't do work if you don't need it done. It's good for repeating work. Promise isn't repeatable. Once you have a promise, it'll deliver a result and then that's it, you'd have to create a new promise. So in a way, signals seem to be promises because you could do everything you need to do with a signal or with a promise you could do with a signal. So I've seen it said that signals are like computation. It's kind of like you set up this thing that has some input and then it does this a bunch of computations. So it's sitting there waiting to do something for you, you just have to hook it up to do things. So what are some examples of signals now that we have this concept, where are they in our apps? So lifecycle events. We have UI application events that we want to monitor. We have view controller events that we want to monitor. These things are all signals. Touch events, of course. Human input, I guess that's touch events as well. Sensors, so your GPS signal, anything that's on the device that measures something can do that. Those are signals. File layout, just kidding. We got rid of the question. Who does file layout, right? No. So now we'll look at operators. Operators are the key part to the signals for factoring we did. Without operators, it would kind of be a useless refactor. It's like, okay, that's nice. So I like to think of the key word, or operators as key words. So we all know Ruby has its key words and Ruby has operators, and Ruby has standard functions that more or less are key words. They're part of the standard library. So look at operators as key words. So don't judge them on their name because they're just kind of, we don't judge key words on their name. They're just part of the funding. So with these operators, some signals, they're like programmers. Sometimes we like to work alone. Sometimes we work together. Signal operators do the same thing. Some of them are just operating on a signal by itself. Some of them combine the signals together. So we all know map, filter on, signal is the same as rejected. Ruby, ignore is kind of the same thing. You can take, it's like, dividing up your signal line. Just want the first thing, or I want the last thing, or I want to skip a few. Distinct and children change. That's kind of a neat operator. Oftentimes on the callback, it's like, oh, we have the same value from the last one. Is the new one the same? If it is, well, we don't want to do anything. So you can kind of see that there. Instead of having this code inside of your callback and doing this everywhere that you need this kind of behaviors, you apply this operator. So it's a little bit more declarative. For scheduling operators, maybe you only want GPS updates. Maybe you only want them every so often. So you throw out delays. Maybe you don't want this to happen right away. Deliver all of that dispatch, a sync, and then time out. Maybe I want this to know if this thing doesn't finish within a minute or a second or some period of time. So I talk about combination operators. You have two signals, you can combine them. Zipping them is like, so combined latest will take, as soon as either one, like if you have two signals, combined latest will send a new value with a pair whenever either one of them changes. Zip will send a pair when both change in lockstep. So you can model your behavior that way. And Kat, we saw earlier, that's sequencing operators together. One thing, nice thing I've talked about here and didn't go over in the code, but whenever there's an error at any step in that sequence of composed operators, that aborts everything. So instead of having to do your error checking where it's like some method takes an error pointer. Okay, now I check to see if it does anything. If so, maybe I return early and then I do my next step that might also have an error. Errors immediately propagate out and all the rest of the work isn't done. But we have operators that allow you to work with those. Side effect operators, it's nice to explicitly say, hey, I'm doing something outside of this computation. I'm not passing values along. I just want to say when certain things happen that I do this other time. This is good to know, you can have signals, a lot of things as they happen. So as Ruby developers, everyone here should be probably pretty familiar with immutable versus mutable types or instances, I guess. So signals have an immutable error. It's obviously things change inside, but from the outside, once you create a signal, it doesn't change. So all these operators are like map in that they return a new instance of a signal and they don't modify the original one. So it's kind of, I was a bit of a jerk earlier to put exclamation points on everything because it doesn't work like that, but it was for syntactic friendliness. So one of the stumbling blocks that people face when learning to react with coppers, they're gonna be seeing signals of signals. So instead of like a signal of a value, like an event or some, the current user or whatever, sometimes you have signals of signals and we saw that when I was throwing in those flattens and concats earlier. The reason is because when you do some work, like a signal represents some work, a computation, it's going to be into more work and that work you might also want to structure as a signal. I'll get into some examples because right now it's quite kind of big, but essentially the longer you go, signals will be everywhere and you start to see them. And these operators that I'm gonna show, therefore arranging and sequencing when you've got signals of signals. So we talked about flatten before. Flatten is basically everything's in time. So if we have a signal of signals at great thing and inside there was some signals being sent on it, by flattening it, we just get them in order, natural order of time. An example of where you might want to flatten is, let's say you've got a chapel app. There's a signal called members that sends a new user every time a user joins the chapel. Well that user is going to send messages to the chapel. So that message is there as a signal. So we've mapped the users into a signal of messages and message signals. But we just want messages, so we flatten. And cap is the second type of signal to signal operator. And this one's fairly logical. It just puts things in the order of the signal as they come in. So the first signal was A, so all of its values go first. And only then does B get subscribed to and B work by more C. So look at that a little bit differently. We can see here in a different animation that things go all of B and all of C. Where you would use concat might be in a multiplayer game, maybe each one gets some number of actions, but when it's your turn, your actions should all come first. Then it's the next player's turn. So we've got signal players, for each player we're going to get their turn actions or we're going to concat me because you don't want people going out of your way. Switch to latest. This one isn't used as much. It's often used for network requests. Basically, it's like, as soon as another signal comes along, it cancels the signal preceding it. So A, not to send a value, but then B came along which canceled the rest of A and allowed B to do its thing. And finally C came along which cancels B and allowed it to do its thing. An example of this might be streaming music. You've got a music player, you're on a playlist and the user hits the next button. So you want a previous signal for the streaming media to be canceled because you don't want to hear two things going on at the same time. And you also don't want to let the previous song finish. So there's this flat map in Reactor Coco. It's kind of gets special treatment but basically it's just a pull in of map and qualify flat. So all the maps and plattens I used at the beginning they could all be replaced by flat on map. It's sort of special for historical reasons. But a lot of people get hung up on it because signals of signals is kind of confusing. But also the name is so generic and it kind of seems out of order. So I just wanted to make a special point that this is kind of like the B-based Reactor Coco here. You're going to have to get your feet wet with it before you can really sort of understand it because the name just doesn't tell enough. Okay, so that's the end. So my advice for learning. I learned through being pretty regular on the GitHub repo. Everyone who's involved in Reactor Coco is pretty amazing at helping each other out. So if you want to learn, please do ask questions on the GitHub repo. Stack Overflow usually gets answered there too. Watch there to answer people as well. So language of only. So I think whether it's promises, signals, whatever, I think we're going to start to see things like this more going forward. So just sort of be aware that things are changing. There's a Reactor Coco 3. Feel free to get started with it but I wouldn't recommend it. It's simplifying a lot of things and it's API compatible but it's also still in development so the current version is Reactor Coco 2 by the way. So next Tuesday if you're interested at GitHub's offices you're doing a rack developer meetup starts at 10 or 11. And so people on the core team are going to be speaking about Reactor Coco and there's going to be a Q&A now. So if you want to ask questions and learn more if you've got your own things that you've faced and you want to answer them come there and learn more. For the reading I will go over these but these are probably the ones that I thought were best. I will point out here that this one's about promises but I love reading it. I've thought about two thirds of it all applied to Reactor Coco. So it's an interesting read. And one of the people active in the Reactor Coco community Bob Sprint's got something he's working on but it's a really good read but he's not done yet. And then just thanks to some of the Reactor Coco people and some friends and family that help you out.