Welcome back to our discussion about futures. And I left you a little bit in the dark the last time, when I showed you how to express reading from memory followed by sending the packets from The US and Europe back with futures. And I don't know if you remember. But our code looked a little bit like a mess. Where we couldn't get, you know, everything to wire up together. But fortunately, futures have a. A lot of higher order operators defined on them. And you will recognize the same higher order operators that we saw on try and that we see on list and that we see many, many times everywhere such as filter, flatMap. And then of course there are certain domain-specific operators that are only defined on future. And that one is recover width. And recover width there, you see, takes a partial function, that takes a throwball, and returns a future. All right? And there we have our friends the future constructor. Now let's see how we can use this to improve our code. This is what we were stuck with. We read from memory. That packet onComplete. And then we had the confirmation of the right type. But it's all this pattern matching and nesting. It just looks messy. This is not code that looks beautiful and elegant. And if we're doing functional, programming style coding, one of the main things that we want to achieve is that the code looks elegant. This doesn't look elegant. How can we improve that? By using flat map. So flat map, again, will hide all this plumbing and better matching for us such that we can ride nice smooth straight line code. So, let's use flat map and here we go What we do is we read from memory. We get a future of array of bytes that's called that packet. And then we just flat map over that. So flat map will take a future array of bytes and give us in that function p is now of type array of bytes. And now we can send it to Europe which would return a future of array of bytes. And the type of flat map go here, will all work out. So I'm pretty sure that you agree that this code looks messy, and this code looks beautiful. So again, flat map comes to the rescue. All right, now let's dive in a little bit and look kind of how packets are sent under the covers. Again, this is all and the reason is that we need some concrete code to build some examples But this is, of course, not production code. But let's look here. Imagine that we have an imaginary HTTP library that has a constructor. That, given a URL and a request, will return a response. Now, an HTTP library is probably going to make a call across a network. So the result of calling apply on HTTP will be a future of a response. And it runs an HTTP request asynchronously. We don't care. As long as, given the URL and the request, we now get a future of a response. Now how can we implement sent packet from the U.S. to Europe and back with this? We first create a URL to some server in Europe. We create a regress from the packet. And then recall that we could then filter such that the response is okay. And then we map the response back to an array of bytes. Now this is still not safe in the general sense because it can still fail. Because maybe, the packet, the network is down so this packet will not reach Europe. So let's try to make this code more resilient, all right? So we want to make 100% sure that when we send the packet, that it actually reaches, the server in Europe. One way to do that is, why don't we send this packet kind of twice. All right, to two different servers. So here is what we do, we send the packet to a mail server in Europe. We send the packet to a mail server in the U.S. Just, you know, to be safe. And then we zip The confirmations to get the a pair of the response from sending the packet to Europe and the response from sending the packet to the U.S. Right? So now we should be safe because of our something it's kind of twice. But is this any better really? Well not, because if you remember what ZIP does with lists, ZIP, if it takes an empty list and another list, it will just return the empty list. So, ZIP will always confirm to the shortest list. That you're zipping. And the same is true when you're zipping two futures. In that case, the error case is the empty list, and the success case is the non-empty list. So when I'm zipping two futures, and one of them fails, the whole zip will fail. So even though I'm doing a lot of work to send this packet to both Europe and back it doesn't help me because the zip will fail when one of them fails. All right, so this is not very resilient. There was these two functions. The one that I showed you but there's another one. recoverwith and recover. And you can see that recoverwith looks a little bit like a flat map. Because it takes a function that takes an exception and returns a future. So it's going to be the error case for flat map and then we have recover which takes its role every. Which is kind of the map for the error case. So let's see if we can use these functions to write a more resilient version of sending packets. All right, so there was our old version. We would just kind of send it. What we're going to do now is we're going to send the packet to Europe first. When that fails, we use recoverWith Okay, and then what we get, is we get a function from to Future of T, right, that's what we need. So then we just send it to Europe. And then, or sorry, to the US. and when that fails, we just return the Array message, with recover, and if it succeeds, You know, we're done. All right? Now the problem with this code is that we're really trying to send the packet to Europe, but when it goes wrong sending it to the U.S. we get the error message for the U.S. So this code is still not really good. But it's already much better than our naive attempt, right? The thing here that I want to focus on is that recover and recover with are like the map and the flat map, but then for the error case of the future. All right? So instead of getting the value, they get the exception. But then the signatures are the same for the rest. So there's an error channel and a regular channel. And they have the same operators defined. On then. All right. We're going to revisit this code in the next section. And then we're going to to do a little bit of geeking out and trying to do some hipster functional programming. So see you soon.