 The sponsored track, they put it all the way in their coins. So I want to talk to you guys a little bit today about Skylight, although we really did shanghai this talk and turned it into a rust talk. Since it's a little bit about Tilda, we started the company back in 2012, and we're really pretty proud and we work on a product called Skylight and DHH's message yesterday about being like a small team, and needing to put tools into your backpack that are going to let you compete with the big guys. Actually it really resonated with us, because we only have five engineers on staff and we're building products that compete with companies that are IPO or are probably IPOing. Yes, like very much, much bigger competition. And fundamentally what that means is that we need higher leverage tools. So when we built Skylight, the thing that we really wanted to solve, the thing that really put a fire under us was that all of the tools that we were using to measure the performance of our applications were recording averages. And as DHH said, it's a visit of DHH's blood test to make up for my Twitter feed yesterday. So DHH wrote this really great blog post in like 2007, it's like ancient times, where he said our average response time for basing up right now is 87 milliseconds, which sounds fantastic. And he believes you believe that all is well and we wouldn't need to spend any more time to optimize the performance. But that's wrong. Average number is completely skewed by tons of super fast responses to feed requests and other cash replies. You have a thousand requests that return in five milliseconds, then you can have 200 requests taking two seconds and still get respectable 170 milliseconds average, useless. And I actually think it's worse than useless, I think it's accurately misleading. So instead what we need are histograms. We're like great, we have received this wisdom from DHH, so let's go build a product model. And so that's what we did. We built a product where instead of giving the average, you can see a histogram. And this is super important because looking at a histogram makes something just so obvious, like you can see cash hits and cash misses because of bi-model distribution. You can also see the 95th percentile, which gives you a much better sense of what the average worst case that your customer is experiencing. And we did that all using very high leverage open source tools. So our back end, in particular, is built on a product called Hatchestorm. I don't know if you can read below. It says distributed, resilient, real-time. I wish we had known when we figured that that was a pick-two list. Carl had a road to get. Anyway, you may have seen our talk. If I grab a slide, I apparently grab all the animations that come with it. But we gave a talk on our... So this year we want to talk about a different high-level tool, which is Rust. So our tagline for Skylight, if you can really motivate us, is how do we give our users... We just don't make a bunch of data on them. How do we give them real answers so we can be set through all the data that they don't have to? And as it turns out, doing this Answers Not Data approach requires a lot of data. We have to collect so much information. And when we wrote the first version of our agent, which runs inside of your application, we wrote it in Ruby. It's really great, you know, Ruby. But we quickly realized that if we were going to collect the amount of information that we needed to build the products that we wanted to build, Ruby just had some fundamental performance problems that weren't going to be acceptable. But we really needed something, but we really needed a tool that was going to give us low-level control, like a C or a C++. But we were afraid, because Yvette and I were afraid of mediocre programmers. And we know that we're giving our software to run inside of your application. And the idea of us writing something with, like, a segfault that would crash your apps is just, like, totally terrifying for our application. We needed something that would give us the high-level safety guarantees of Ruby, but with low-level control and this low-level access. And then Rust was the answer. Rust came out. It was still free 1.0. But we decided to make a big fed-on re-roll file. Well, it's going to be a big fed-on re-roll file. We got a semantic version of what's over here. So we decided to rewrite our agent in Ruby, in Rust from Ruby. And we called that our featherweight agent. And this, I have to say, has been one of the best decisions that we've made. It was a very nerve-wracking to bet on this free 1.0 program line, which is low-level, making all these quite intense promises. But it's been really great, because Skylight, the agent now, in addition to collecting so much more information than our competitors, just sips resources if you compare us to it. Because we're writing this code that's essentially operating like C, in addition to better performance and being so lightweight in terms of resources, it also lets us build features that we would never be able to build if we didn't have that low-level assets. Being able to write something in native code lets us go a level deeper into MRI itself. So, for example, this year we launched a new feature that actually shows allocations. So you can actually see how much memory is being allocated in your Rails.in production, which is huge when you're trying to track down memory issues. Now we can do that at a really granular level as we build up. Yeah, play it to the minute. And this is also letting us check a new feature that we're announcing today called Trends. So Trends is a new weekly email that we'll be able to subscribe to for launching at this week. You'll get a weekly email showing you not just magnitude percentile, but also your median. So this is a really great way to protect changes over time. So the thing that I would ask you to do is going to get into the meat of the whole matter. But the thing that I would ask you to do is with a language that offers you low-level control, but high-level safety and expressiveness, if you're a small, proper team, what can you do? What new opportunities and new features in your apps does that allow? So fell for the new here is Kuda with his rush field. Yes. Hey! So those kind of colors in the rust? Oh my God. Yeah. How do you change the colors in the rust colors? Uh... There's like a... Yeah. Oh yeah. Let's do this. All right. I can hold it for you. I'll be there for you. Okay. So, today we're talking about rust. This is the Rust logo. I'm going to plot programming languages on this expressiveness and speed graph. And I actually kind of applied this to be a somewhat pointless exercise. And I use JavaScript as sort of an example of this, which is that, you know, when I started writing JavaScript in 05, JavaScript was pretty bad at expressing this axis and even worse on this speed axis. But there was one thing that people underestimated on JavaScript and what they underestimated was the fact that JavaScript was everywhere, right? So JavaScript was on the client side with basically all you got to write. So you wrote a lot of JavaScript on the client side. But the server size is very tiny, so like maybe the red one there is reals or something. Yellow is PHP. So JavaScript was everywhere on the client side. It wasn't very popular. The server size of people kind of dismissed it, but they sort of missed the ubiquity of JavaScript on the client side. And what happens when there's an advantage like ubiquity is that people go and they say, okay, well, JavaScript is long on the speed and expressiveness scale. Well, let's write V8. We write V8, boom, now it's way faster. Well, people don't think it's expressive enough. No problem, we'll go and we'll make it more expressive, right? And so this idea of programming languages as living in fixed places on the next wide axis of speed and expressiveness is kind of not the way I think about programming languages. I think about programming languages and tools in terms of enabling what they enable. So obviously everyone is here because of Rails and for a lot of people, Rails enabled you as a person who may not necessarily, at least for me, I'll speak for myself. Some of you didn't really know what I was doing when I started. It enabled me to build pretty ambitious stuff that I wasn't able to build before. We were my number for a simple reason and the thing that was really about Node, I think, is that Node allowed a bunch of people who only knew how to write in front-end but like 99% of people write in front-end using JavaScript to let them write back and stuff. And a lot of people like to say like, oh, do you really want those jQuery jockeys right on your server side? That's like a pretty good joke that you can tell. But the industry is actually controlled largely by a lot of people who may not necessarily want to build that thing but end up getting pressed into service. Like for me, that's definitely my story. I got pressed into service into a lot of things I wasn't ready to do and so for me, looking for a technologist that enabled me to do my job is so important. Rust is really good at, Rust is not ubiquitous by any stretch. But Rust actually enables people like you and me, Tom, to be systems programmers. And usually when I say that, I say, oh, yes, Rust will enable you to be systems programmer. I get a work like this. Like, I'm not a systems programmer. What are you talking about? Somebody else can be a systems programmer. Although as Tom pointed out, sometimes you don't have choice. But then usually when I get asked and say, no, it's like good, you may want me to end up in a situation like that, people say, oh my God, that sounds really scary. Systems programming sounds like super hard. Obviously I played the C a few times and that was crazy. Sometimes I was super dangerous. So then you're like, no, Rust is great. It lets you, you know, it's easier and it has some of the high level affordances. It's also not as dangerous as you, as C, it's like safe, actually. And then people say like, oh, so systems programming seems cool, but like, what is that? Like, what is systems programming? So what does that mean? What is the definition? So there's actually a lot of definitions, but I'll just give you my personal take on it. So there's like a few different things that systems programming means to me. One of them is you get to write a code without a GC and there's a lot of reasons why you might care like if you're a high frequency trader, you care about GC pauses, if you're asked you don't want to invent a GC language inside a GC language, right? So there's a lot of reasons you might want to program without a GC. Also programming directly against the metal. I don't mean like the way no people say programming on the metal. I mean literally like writing against the lowest levels of abstraction that you have access to. And doing that without additional costs that the additional abstraction costs. So you shouldn't have to write extra layers or have extra layers of costs just to program and talk to the program, right? Also in terms of runtime, most programming languages have a pretty heavyweight runtime or an involved runtime. Usually when people say systems programming, what they mean is that there's like either no runtime at all or the runtime is very lightweight and it's pay as you go as you need it and you use it. Also this is like our thing that came out of C++ but I think it's important is like you should be able to write abstractions and those abstractions should not cost. You should be able to write functions, you should be able to make structures, you should be able to organize your code in a good way and not have those abstractions at additional cost as you go. And finally I think the thing that systems programming most is is everybody's written code, like you write a movie code and normally the good answer to Rust is like well it doesn't end up mattering. Who cares? I'll just write my Rails app and it'll be fast enough and it doesn't end up mattering. But occasionally you end up writing code where it doesn't matter. And this happens basically every app where there's a performance critical area and it just doesn't end up being sure anymore that it doesn't matter and the amount of time that it takes you to get to a reasonable performance is actually more writing in a language like Ruby than writing in a language that's optimized for a good performance. So that's sort of for me system programming is when it turns out that the story that we taught ourselves about performance not mattering for the cases where that doesn't end up being true. That doesn't mean a bunch of stuff though. It doesn't mean malignant free. It doesn't mean if you're writing a language that doesn't mean you're writing code that only talks to Unix. It doesn't mean you're writing handcrafted made files. It doesn't mean you have to care much about what the linker's doing. And it doesn't mean that your entire application is written in a systems programming language. It may mean that you're writing using a little bit of systems language for errors where it matters but most of your apps still written in something like Ruby. So a good example of this like Tom said is Skyline. So Skyline basically used Ross because we needed to embed a programming language without the programming language and two GCs is not good. We needed to hide performance and we needed low memory. So for all those reasons we ended up going with Ross. Firebox, sorry, Mozilla actually is using building Ross for kind of a different reason which is that they're building a new browser engine called Servo and for them they needed to build something that was fast, safe and parallel. So they really wanted to be exploring different parallel options and interestingly the Servo team is like seven people so you want to talk about a prepper team or five people building Skyline that's seven people building a browser. And they're using Ross because it allows them to explore ways of writing a little bit but you can normally write C++ you can normally write Ross with C++ but less than explore that kind of performance profile about being able to do parallel stuff. So that ends up being pretty important. So those are all reasons why you might use Ross. I'll talk a little more at the end about Ross and Ruby but before I talk about Ross and Ruby I want to talk a little bit about how it works. So I'm going to talk about Ross but before I talk about Ross I want to talk about sort of how garbage collector works. So here is some Ruby code you can see I have a very simple structure I have a class it has a point it has an x and y it's a Ruby audience so you should know what this code does it's very simple and I have a link function the link function basically makes a new point a couple new points makes a line and calculates the length So what happens is I'm going to this link function I make this point the point is to be created it goes into the heap somewhere I make another point no problem goes to the heap somewhere I make a line goes into the heap of course that line points at the two points I go into the link and then at some point in the future so that those objects stay there chilling out at some point in the future something stops the world and it goes again and looks into what's going on discovers that nobody else needs those objects anymore and includes them all and that's actually a pretty good story for staging because basically by definition a garbage collector ensures that you can't use an object sorry the object is clean up only after it's no longer be used so the whole concept of a use after free bug is impossible by definition you have a garbage collector use after free is impossible free only happens after use is done that's the point of garbage collector but that means that you need a garbage collector and there's another way of dealing with memory that is how the methodology for using memory for dealing with memory C or C++ and that methodology is called ownership and the idea of ownership is basically that whoever allocated the object is responsible for de-allocating so if I make the object I have to de-allocate it and the reason why this is good obviously is that it means you don't need a garbage collector the reason that it's bad is that now you have to keep track of all that you have to make sure that you do the right thing and if you do the wrong thing if I take the object and compromise to create it basically game over now I try to use it later and I get a cycle right so the idea of my ownership is how is the methodology for doing systems programming but historically actually doing it was very hard so let me try to give a simple analogy so let's say there's me and there's Carl in thinking man pose and there's a book shop I basically go to the book shop the book shop says okay here you you can have a book it's my book now it's my book I bought it so now I bought the book from the book shop now I'm allowed to destroy it or burn it not the best analogy so I'm a good use of the blame energy so because I own the book I am allowed to destroy the book right it's my responsibility I don't have to ask anybody else for permission right now once I own the book once it's my book I can also give it to Carl and now that I've given it to Carl Carl is allowed to dispose of the book and I but I can no longer dispose of it I've given it to Carl it's now Carl's book so one way that you might think about this is that ownership both in the real world and the programming world is basically talking about the right to destroy something so let me show you basically the equivalent code hopefully people can read this code probably not but sorry 1024x760 so you can see on the top that there's a book it's simple if you're like familiar with any type language it's a book it has a title it's a string it has a bunch of chapters it's a factor of strings then we have a functional name and I'll just walk through what happens here so what happens here is the first thing is we say give me a book read the book out of the file system and then now the book exists and it's owned by this function so ownership of the Rust is usually rooted in a function so the function that's in the middle of being called own the book now I don't have to print the book and that's great the book has printed to the screen and I leave the function main so now the function main as an owner doesn't exist anymore and because the function doesn't have any work you should know it's a lot of manual memory management here what happened was that because the function main owned the book and the function main doesn't exist anymore the book gets destroyed and that's I think that's a pretty good starting point if you want to try to do automatic memory management but of course if only the function that ever created something is allowed to use it that doesn't make very interesting programs so let's look at a little bit of more involved a little more more of an example it calls the print book function to print book and so what happens here is that we make the book as before now the book is owned by the main function now we call the print book function and the thing to know here is that the print book function just takes the book capital B book no extra signals or anything like that so because of the fact that it takes the book by default that means we're going to transform it and now what that means is that the main function no longer owns the book and when it leaves now it is responsible for disposing of the function and the book gets destroyed as you might expect now you might be thinking okay so that's cool but I've written a lot of Ruby and if there's nothing really stopping me in Ruby from after the following print book going and using the book again right so if you follow this methodology over here what's going to happen is that the main function is going to try to access a book that was destroyed and we said before that we can kind of let's go back and let's look at this example where we do the same things we did before but after transferring the ownership to the print book function we try to use it there we try to print the number of chapters so as before we make the book you know we put it it's owned by this by this function the main function we print the book we transfer it as before the book got destroyed now we try to go back and print the book well actually no what's going to happen is we didn't actually get this far the compiler actually discovered that we did this ahead of time it says you can't do that and what it says is you use the moved value the value is transferred the ownership was transferred into print book and you're trying to use it and then you get a little note that says no the book was moved here so in the real output there would be like a little arrow pointing at the print book function so you say okay I see that I transferred the ownership I'm not allowed to use it anymore and sort of like I said before so this is I think this is fine for simple examples but you can sort of think to it that this is not the whole story this is not you can't really write you want to do something with the value you have to give ownership to the function that wants to do something with it that's not that's not very intuitive and to deal with that in the real world in the real world of transferring ownership we deal with that by saying you're allowed to lend something so I go to the library the library doesn't have to give me ownership of a book you can lend the ownership to me and then I'm giving a promise to the library that I will return at a certain point right so the way we deal with the problems in the real world is by borrowing ownership and rust so let me let me give you an example so I have this book that I got from the library and I say to Carl hey I would give you this book but you need to return it to me by 5 p.m. on Friday right and as long as Carl returns it by 5 p.m. on Friday everything's great now the problem is that in the real world there's nothing enforcing that rule so I can say to Carl I'll give you the book back at 5 p.m. and then he doesn't give you the book back by 5 p.m. it's basically now I'm in trouble somebody else wanted to see if we can do better than that so let's look at another example with borrowing and you'll notice that this is basically the same program that we wrote before except this time when we call print book we use the ampersand symbol before the book and we put an ampersand symbol before the capital B book on the bottom and the only thing that we're saying here that's different from before is that instead of transferring ownership from the main function to the print book function we are lending the book to the print book function and it's required to give it back to me at the end so let's look at what happens so I start off with the as before the book is owned by the main function but now because I call print book with the ampersand it gets lent to the print book function the print book function prints the thing to the terminal and then when it returns it gives the book back to the main function and now because of the fact that it gives the book back to the main function when I go to print the line the main function still owns it it can happily do that as expected so that was pretty pretty nicely but there's one additional step that you need to understand how the whole system works which is the fact that you can borrow you can lend something that you borrow to somebody else we call that some leasing the idea behind some leasing is that the first person to borrow isn't the last person to borrow so in the real world you can imagine I go to the library the library who lends me a book and the library says hey I need you to return this book by 5 p.m. on Friday great so I remember that I need to return and Carl says to me hey I want the book I want to borrow the book so I can give Carl the book but I can say to Carl hey I need you to give me this book back by 4 p.m. on Friday because I know I can give you a batch of library by 5 p.m. so you can borrow the book but you need to return it back to me then Carl returns the book back to me I return it to the library everything's great again in the real world it starts to get complicated in the real world when you start dealing with some leasing you start dealing with complicated some leasing arrangements and restrictions and that's mostly that would be an honor but in the programming world the compiler can enforce it and so let's look at another example with some leasing that's a little more involved so here the important thing here is that we're able to write arbitrarily involved abstractions just like in any programming language as long as you follow these basic ownership rules so here's the function called main yet we're going to the book the book is going to And again, we're going to bomb or lend the book to the printable function. So it gets the book. It already has barred, but it doesn't really know how to print things. So it's going to delegate that to the print title function, the print chapter function, right? So it's going to call print title. That's going to lend the book another level down. It's going to print line. Then it's going to return back up. Then the printable function is going to go another level. It's going to print the chapters. That's going to go get the length of the chapters. It's going to print the line. It's going to return. The printable function is going to return. And then as soon as the whole printable, the whole main function is done, then it can destroy it. So the really cool thing about all of this is that in all of these, in all of these cases, I think the way, the thing that we're doing is pretty normal, right? It's basically, if you think about it, in most programming, when you call a function, you're basically lending. You're not expecting the thing that you're calling to take ownership and try to do something with it later. But we have to pay the garbage collection overhead in all programs all the time in all cases because somebody might want to do that, right? And in Rust, the way it ends up working is that you start off with this assumption of ownership transfer and you can lend things as much as you want. That's basically a thing you're free to do. And once you've done that, now we can completely eliminate the cost of garbage collection across the entire system. So there's one last video, which is immutability. So far we've been talking about read-only things, and of course you can imagine that if you're only dealing with read-only things, you can lend as much as you want or anybody can look at it, and of course they can't mutate it, so it's totally fine. You can have 50 people looking at something at the same time, and it's fine. But what if I want to allow mutations? Mutations add a little bit of a wrinkle to it. So let's say I go to the library and the library says, here you can have this book and you can feel free to change it. Let's say you can move a bookmark around your fold the corner or something like that. And then Carl says, hey, I want to borrow the book. I might want to say, Carl, you can borrow the book, but I don't want you changing it. And so I can say, hey, return the book on Friday, but don't change it, and you return the book, I return the book, everything is great. Again, human terms is getting you more complicated, very difficult to implement the rules. In rustics, again, it's pretty straightforward to change what we've been doing all along. So the first thing to note is that so far, by default, everything you do in Rustics is quote-unquote immutable. But when we say immutable, we don't mean that the object is frozen, there's no runtime jet or something like that. It's just by default, if you have a reference to some kind of object, you're not allowed to mutate it. The compiler will prevent you from changing it. Now, let's say I want to add a new feature here which is that I have the ability to add a bookmark to the book to say where I'm off to. So now, in order for me to be allowed to mutate that bookmark, I need to start off by saying, give me a mutable book. Don't give me a book, or we'd only book any mutable book. And that's fine. And now, when I call the printbook function, the printbook function, before I just call it with the ampersand, which means I'm lending it to you, this time I'm calling it with the ampersand mut, which means I'm lending it to you and you're allowed to modify it. So I call printbook with the muting I send it over. Now, the thing to note here is that when printbook calls print title, when printbook says I am allowed to mutate it, but I'm printing the title should be mutated, so I'm not going to let you mutate it. And so printbook, when print title works as before, it follows it, does the thing, call print chapters, does the same things as before, and then at the end of my function, I'm basically going, I'm going to mutate the bookmark. So this is a kind of a whole key example because printbook shouldn't be changing the bookmark. But the key point here is that if you look at the main function, it's clear to me that the printbook function might mutate something. So just by looking at that signature, I can say, okay, I can see that mutation might be happening and all the other signatures on this page don't take a beautiful borrow something. So we know that they can't mutate anything. And that ends up being pretty important. That ends up helping a lot. So now I'll just recap by saying there's basically two rules of borrowing. You can have as many outstanding re-only borrowers as you want, so you can, in the real world again, you can't give the same book to many people at the same time, but aren't you programming? You can have as many pointers to the same object as you want, so you can have as many outstanding re-only borrowers as you want. But in contrast, a mutable borrow is unique. If you have a mutable borrow that's outstanding, no other borrow is mutable or re-only can infer at the same time. And again, it's very important to note that this is not enforced at runtime. It's not like every single time you try to borrow something and check to see if anybody else has anything outstanding, there's no, like, mutable locks at runtime. It's all enforced by the compiler, but this gives us some nice problems. So I want to show you some examples. So I talk about what's a lot of and not a lot of. I want to show you some examples of what that might look like. So we start off here, we have this function called same, and the same function takes two books. It follows two books, right? And it just says it's entirely the same as the first title says it's the second title or the chapter is the same as each other. And in Rust, W equals what it doesn't mean to be. It does a deep, deep comparison, right? And if you call same with book one and book two, obviously that's fine, right? I'm allowed to lend something to the same function. These are two totally different books, so that's really fine. Now, what if I, instead of lending book one and book two, what if I call same with book one twice? So again, because this is an immutable borrow because it's a read-only borrow, this is still fine, even though I'm making two copies of that book. So from the perspective of the same function, those are two copies of the same thing or two different things. The fact that it's read-only means that's safe and you're allowed to do it, so that's still fine. But now what if I make another function? What this function is going to do is give you a copy and it's going to take a book and a mutable book and it's going to copy the read-only book's title into the mutable book's title. So here what we did is we said copy the title from book one into mutable book two. So like I said before, that's still totally fine because in this situation we have a book one, we have a book two, we're not going to go anything going on, we're following the rules for borrowing and mutable borrowers must be unique. That's totally fine. Now what happens if I'm going to change it? Now I say we're going to only get one book and then I'm going to call say copy from book to the same book, mutable book. Again, from the perspective of the copy function, it doesn't know that these are the same thing, right? But what it ends up asking is a pilot looks at this and it says you're trying to have a read-only borrow and a mutable borrow at the same time. That violates the rules of borrowing. So error cannot borrow a book as mutable because it is also borrowed as a mutable. And it gives you a note that says the previous borrowable book occurs here, which is useful. And then it says the previous borrow ends here. And basically at the end of the day, borrowing is a secret sauce of rust. Borrowing basically allows you to do very, very involved, complicated, recursive things that you might think you need to go on each one, but by following these very simple rules, you get done what you need to get done. I actually want to skip a little bit here because I want to get to the root beef part. I'm going to skip over the closure or stuff. But the TLDR on the closure is that closures follow the same rules as regular... Closures follow the same rules as regular versions. So if you're using a closure and a closure closes over a variable, it ends up having the same rules. So if you pass the closure to another function, and the function tries to call it multiple times, that would violate the recursive rules and then something gives you an error. You can learn more about that in the Rust book. So what about concurrency? So the interesting thing about concurrency is that really the public concurrency boils down to one thing, which is that shared beautiful state is the root of all evil. And there's basically two strategies that people use to try to deal with this problem. It's called channels. The idea behind channels is that you're not allowed to have two copies at the same time at the same time. If I want to get it with value to some other thread, I have to pass it through a channel and then you base it in cannulas. Another strategy that's used is functional style, which is that you can't mutate. You can never mutate anything, and you never share a beautiful state. Rust sort of does a combo. It says you can have shared state or you can have a beautiful state, but you can't have shared state that is also beautiful at the same time. The exact same idea as the original rules of borrow that we just had before, which is that you can add as many outside and read only bars as you want. That's shared state. Or you can have a single beautiful borrow. That's a beautiful state, but you can't have both of them at the same time. So you can have alias state or you can mutate but you can't have both at the same time. And if you use more rust, you'll see that the send trade and the send trade are basically the ways that internally rust enforces this. It's not anything special about threads or any particular bad structures in rust. There are just two trades that represent thread safety, essentially, and any library that's written, like Carl has a bunch of libraries that feel Eastern Chronos Io or RNC, and they're able to implement these rules themselves. Just a couple simple examples here. So we have the spawn function. The spawn function takes a closure here. You can see that if we call this spawn function, and we try to access a book from the outside, it's going to tell us that there's an error, and it's going to tell us that the book doesn't look long enough. And the reason for that is actually kind of like the dependency on the employer stuff. But the basic idea is that the closure could run at any time. So we call spawn with the thread that closure could run at any time in the future, but we know from before that the main function owns the book. So we can't let the closure arrive and use the book at any time of the future because we know that as soon as the main function gets exited, it's going to clear the book. So that's an error. Basie says the book does not look long enough. This is compiled by an error. And we add the word. We add move to it. And Basie says this closure is going to be moved out. You can feel free to move anything from the aeroscope beside it. And then that becomes just a regular transfer of ownership into the closure. I'm going to skip the next section. So one thing I didn't talk about, or seriously I didn't talk about, is sort of high level productivity. Maybe you got a sense of that from the one slide that I showed the closures, but it also has a lot of higher level ideas that are pretty familiar to higher level programming people like people coming to Ruby for Python and JavaScript. So there's things like OO. So you can have a type that you can implement. There's things like traits, which I don't have a good example of. But the idea behind traits is sort of similar to Ruby mix-ins, or big Ruby refinements, which are like scope mix-ins. So you can write things like happy support where you can implement a method on the one function, on the one value, where you can implement, you can say like one of the things that I go, or you can implement traits that go interfaces. So there's sort of this very flexible way of dealing with kind of mix-in type of situation. There's also aerators, which are a way of doing something that looks very groovy-ish in the sense that you might map, filter, reduce over things. But under the hood ends up being profiled to be effectively as fast as the things that you would have written by hand. And that's just sort of magic LLVM stuff. There's also enums, which is, if you're familiar with other languages, where there's like something with a variant. You can have enums, you can also put methods on this one now, which is awesome. There's also over-loaded operators. There's another thing, it's going to do things that look like indexing operator, but also things like the plus operator. So all that's pretty cool. I didn't talk about it because it's not like, these are all like cool things about Rust, but they're not part of the big story. The big story is that ownership lets you do really low level things without the fear of psych faults that you have. And I wanted to show just a really quick demo before my time is up of what that might look like in Ruby. So let me, I should bear on my screen. So I don't have much time, but basically, I look, make it bigger. Oh my God, this needs space. So basically, I wrote a little, a little rack handler. So this is a rack handler you can see through me. The thing on top here is kind of the interesting part of this, which is I'm using a built-in thing in Ruby Fiddle, which Erin has talked about a lot. And I'm basically just saying, okay, I want to load, dynamically load this Rails object that I got from Rust, and I'm going to define three functions, either a function, or a port function, which takes an analytics, and an analytics function that returns to analytics. I make a little classical analytics, which just wraps that, so you can see it initializes the calls you have to buy, the player, it's basically calling into Rust. So all these things that are happening here are calling into Rust. And then I wrote a little rack handler here, which is just an analytics handler, and when you go to slash report, it calls report, gets a string back, and otherwise, it just increments and requests URI. If I go into the Rust code, we'll see that the Rust code is actually a pretty vanilla Rust code. I have a structure here called analytics. It has three hash maps, and then for host schemes and endpoints, and then when you call Inker, it basically goes, okay, increment, parse the host, make sure everything is okay, basically failed, the inside of the value URI, and then increment each one of these three hash maps with the information we pulled out, and then also increment it over. So we have some Rust code that does what we wanted. Now the cool thing here, the really interesting thing here, is that you see this, no mango thing, and then pop X certain C. Other than this, it's pretty vanilla Rust. But by adding these descriptions here, what we're basically saying is, from the perspective of any other programming, it does not just treat this like C. So you can see here, for example, this Inker function takes an analytics and a buffer, and if I go back into the, if I go back into the config.ru, you'll see that that's, Inker function takes a C point of analytics and a buffer. So the cool thing about Rust is that even though it has always highlighted the same guarantees and syntaxes in exactly like C, the underlying semantics that you can tell Rust like this should be usable from C are exactly the same as C. So now let me just run. I should actually show you, so Rust has this thing, has a, sorry, Rust has HacketManager, so there's cargo.toml, which is the HacketManager description. You can see I have a Rust copy demo. I have some ponders. Then I have, I describe my library. I say it's a dialog, which is important for this demo. And then I say it has a dependency on URL and it has a dependency on Ruby Bridge, which is a library that I wrote for this demo, which is basically just the thing that gives you the buffer transaction. And then if I go to cargo.bill, that's that's release, it actually does nothing. And the reason of that is that I run for both is that it sees that I already built that. So my RMRF, the target directory, and then runs cargo.bill again, it kind of works like a bundle, right? It's basically like, oh, I see you already downloaded those things, so no problem, I'll not download them again, but I'm going to compile them one at a time. You can see that it's compiling the Ruby Bridge crate and the URL crate, which are basically the dependencies that I listed. That's automatically, you don't have to do anything other than save and dependent on it. And then I'll just point out in the Rust code, the RMRFs, you can see on the top here all I have to do is say, X-turn crate URL, X-turn crate Ruby Bridge, that's all you have to do to get cargo to do all to go. So if you've ever written, like, C or C++, that's like a billion times simpler to deal with dependencies. It's like, right in front of me, in a modern programming language. So now, now I'm just going to do a bundle exact, rack up, can't think of RU. I'm actually inside of a Ubuntu VM, so I have to minus O0, O0, O0, O0. So then, I'll be open from, I'm going to go to... Okay, so you can see, it says success implemented Ubuntu.dev, I can go to Like, Oh, whatever. Your own... Oh, yes. So, I flashed it on screen, but it's very simple. You go back to the configureRU, you'll see, It's, this was a benchmark You can see it basically doesn't do anything as a call, it basically says, if you're report, then return 200 with the report that we get over the application rust, otherwise, call the interfunction again over the application. Basically. So, you can see now the actual work outside of Ruby, it's just calling in the Rust through that little, little branch. So, I can say success, I can do like, Ubar, awesome, and then if I go to 40.9.2 slash report, you can see it'll give me a report, and I face it, it's too big. So, this is basically the default debug version of that structure. So, actually, if you go back and look at that structure real quick, with RS, you'll see that I derived a debug, basically, it says emit the code that is necessary to print the debugging version. And then if you look at the report, you'll see that the report is literally the same format that debugging code, and then send it back over as we do the debugging, like a heap-allocated debugging, that kind of thing. So, and this is basically just Ruby printing that same thing, I mean, I called you outside of the Ruby script. So, you can also see that it's definitely working, because you can see Baylight code that ICO is incrementing as I go. This is definitely, definitely real life. So, I face it out of time here. But the key point here is not really anything about this specific example, but just to show that Rust-B produces a dinosaur file which you could load into Ruby. Ruby hasn't built in Fiddle. Rust is pretty good, I have to buy. So, without that much difficulty, you can take something that might be computationally intensive, and convert it into Rust, and then call it Ruby pretty easily using like normal tools that you're using. Basically, we'll look for correct. So, I, both these examples, sorry, the example and also the libraries that I use, which are very tiny, are on my GitHub, so github.com.com. It's like the last two re-booking version. And I'm happy like anytime the next we face any questions as I put random numbers. Thanks. Thank you.