 Alrighty. Welcome everyone. So this talk is Rust for Pythonis by Rob. Please give him a warm welcome. Thanks. So questions during the talk are completely fine. Just throw your hand up. If you're over there, make a sound as well. Because I'm going to be looking this way. Every time I see the camera I'm just going to sort of gaze off into it for a while. Let's not let that happen too much. So I started using Rust for a pet project when I was between jobs a few months ago. And I wanted to do some stuff that was right down in the operating system, talking to network cards. And I thought, you know, Python, which is in many ways my favourite language, might not be a good fit for that. And then I looked around at the other languages and I was like, yeah, I've done C before and I know what that's like. And there's Go, but Go does the screen threading thing. And I actually wanted to have stuff that works directly with a network card. I care intensely with that particular bit of code about threads and what's going to execute where. So that wasn't a good fit. And I've been interested in Rust for many years. I dabbled with it years before when it was pre 1.0. And I was like, maybe it's time to dust this off, clean it up with an iron brush if you will, and get a good look at it. So I did that and then Tommy's like, you know, we're holding this conference, you should put a talk and I was like, I don't really have any Python talks that I haven't given so many times on board of them, but I could talk a bit about Rust. He's like, sounds great. So if this goes badly, all of which to say, if this goes badly, it's Tommy's fault, not mine. So I'm going to give you the whole talk in about 30 seconds and you can go and we'll stay and talk about some of the details. So Rust is really nice. It's an interesting language. I'm not going to try and teach you the language today. That would take too long. There's a lot to it. But I'm going to give you hopefully some of the flavor of it. And some of the bits that really stood out to me has been different from Python. Things that make me stop and think about what I'm doing. You can call it from Python. You can integrate with it really quite well and you can use it for Python extension modules. There's a poster. You should check out Tim McNamara's poster about that. It is enjoyable and productive and like all things, it's not perfect for every use case. But you're not crazy if you sort of sit down and say, hey, I'm going to do something and it could be something that's kind of scripty or could be something that's hard core data processing or whatever. And Rust can still probably do a pretty good job of it because it's a modern language. There's been a lot of stuff that's gone as language design over the last 25, 30 years and the Rust folk learnt from that. So let's talk about what's the same. So Rust has a huge community. A lot of people who sit down and say, you should go and get involved in Rust because it's got a great community. And it really does. They have consciously decided what sort of community and culture they want and they've tried to build that from the way code reviews are conducted to whether they use mailing lists or forum software to engage in discussions about the community. The Python community has discussions about this as well but Rust kind of started with, we know that things can go badly here. Let's think about how to make it go well. So we've both got communities and that sort of thought and care goes into it. It's a general purpose language. So there is, I can't think of something where you couldn't sensibly write it in Rust. Even shell scripting run a whole bunch of processes stuff. Joey Hess has written, I think it's Joey Hess wrote a Haskell library to run command line stuff. So you can do shell scripting in Haskell which is even more pedantic about exactly what types you're working with and so on in Rust. And if you can make that work in a productive way, I'm absolutely sure you can do the same thing in Rust. I'm not sure it's a good idea but I think you can do it and have it be productive and a net positive overall. So I want to talk a little bit about Python. I kind of went off the deep end on profiling this rather than writing the talk. It's why the talk took a while to write. So let me just do a check because I know this is a Python conference but there's also been some non-Python talks here. So does everyone here actually write in Python? Okay so I don't know whether those hand meant yes or no and only half the hands went up. So that's a tight failure. So put your hand up if you don't actually write in Python. Don't as a regular thing. So there's about five or six slides and in fact there's some ex-Pythonists here. So look, Python is a dynamic language. It's interpreted. The types of the objects in it are examined by the runtime as it goes forward. It doesn't figure it out in advance. It has the ability for you to clear what sort of types you're working with with the MyPy work that's been moving into Python 3.5, 3.6 and it's evolving. And this starts to bring a bunch of static analysis to Python. More so than it had before and that can greatly aid in programming in the large. Both when you've got complex things you're trying to represent and also when you're working with large teams. And part A and part B aren't going to get the contract quite right. So having the interpreter and the linters be able to tell you when it's wrong rather than running a five hour test suite to find out that it's wrong is actually a really good thing. One of Python's really nice characteristics is you can do a lot with a small amount of code. Try not to cough into the mic. However, it's slow and I know people are going to have issues with this but look fundamentally it's slow. I've spent enough of my life working around those issues by running hundreds of separate processes doing one request each on web servers even with twisted in the mix to say it's slow. It is, however, very fast to create it. So you've got that trade off. If you are a site like Pinterest which is running millions of requests an hour and you're scaling out to thousands of machines, that's sort of slow and starts to become a big deal. So that's one of the places where maybe Python is, you're hitting the limits there even with PyPy and getting compatibility with things like Eventlet and PyPy. I believe that one right now works but that sort of thing is often a edge case. New things that are done will be done in C Python and then you've got to wait for them to move to the more advanced VMs in the ecosystem. So I thought there's this classic thing, you write a Fibonacci number generator in the worst possible way and then you use that to compare how your languages are. So I thought I'd do that. So here this is the classic recursive definition of the Fibonacci number and I also want to highlight this N colon int that is the MyPy syntax saying that this is an int that it's taking in and this can be completely statically analyzed by MyPy. So it can figure out the types of everything there and it will know that it works well. And for a small example like this it's really not very useful but it generalizes. So this is Rust code. It does exactly the same thing and you'll note, except for the curly brackets, it's almost identical. So the first thing is if you can read Python you can read a lot of Rust. Straightforward, they've got very, very similar roots. The fn rather than def is kind of the first thing and the arrow is the syntax for returning a type. I couldn't remember the syntax for that in MyPy which is why it wasn't in the other slide. Anyway, so Fibonacci 38 is going to make a bunch of function calls. One interesting thing here, this exclamation mark says that this is a macro. So the Rust language can be extended in two different directions. You can write macros which take in the abstract syntax tree and can manipulate them and output some other stuff in a normal compilation that's built in. And the other thing you can do is you can write a compiler plug-in but that's only in the nightly branch at the moment. There's a back port and it gets complex but you can do some really cool stuff and if we have time I'll talk a bit about that. So I wanted to see just how big a gap we had and I know there's a whole chunk of data to put in the slide but talking about graphs from the talk before, who was in the talk before about graphs? Yeah, so graphing is terrible. So I just used the thing that would output a graph for me. The takeaway here is that, so at the top we've got Fib.py is the first one and then the Rust binary was the second one and the Rust binary took 99% less time. So Cpython's kind of interpretive, we don't expect it to be fast when you're making lots and lots of function calls so maybe we should try running it with PyPy, 89% slower. So PyPy is 10 times faster than Cpython for doing that and so here I've got PyPy versus Fibinacci and so I misspoke. That's Py, Cpython versus PyPy, 89% difference but when you then compare PyPy to Rust you're looking still at a tenfold difference in time. 1.3 seconds for 1.4 seconds max versus a tenth of a second so there's quite a big jump there and if you compare them all together then you're looking at four orders of magnitude going from Cpython all the way through to Rust. That can actually make a huge difference. You've got a lot of fat code in your system that you're not really worried about things that aren't hotspots maybe this kind of gets lost in the wash but being able to write inner loops in a faster language is a well-known strategy for fixing computational performance problems and I'll talk a bit about how that's kind of enabled. So for Rust it's not dynamic at all, it is entirely static the functions that can be called in the type and the classes that the type has got associated with it all of that is known at compile time. You can't do any of the tricks you can do in Python where you have descriptors and you can assign new functions to an object and call those functions at runtime, none of that. Well, you could implement using the callable trait and a hash table. You could kind of implement it on top of Rust but it's not going to have any of the performance guarantees that you'd want the other Rust so I really don't know why you'd want to do that. It is however duct typed. So I said classes before and Rust doesn't actually have classes. It has structs which contain data in a particular shape and it has traits which are like interfaces or absolute base classes and they tell you what methods you can call on those structs but you don't inherit. You can compose, you can nest and you can do runtime dispatch so when you've got a trait that says I've got a function thread I can call on an object you can have an abstract pointer to that which you can hand round that hides out the actual data so kind of like a virtual method in C++ or like everything in Python. But the big thing is you're not looking to incorporate implementation by deriving from something you're looking to have this looks like a duck it quacks like a duck I can use it like a duck and then all of your code can do that with different types and it generalizes. It does that through generics rather than through interpretation so you get some syntax, some visual noise to deal with as you do that. One of the defining characteristics of Rust is that it is a very, very safe language. Python is a very, very safe language until you try and use different VMs. So for example, if you run on C Python you know that only one Python bytecode is running at the time. So operations like putting a thing into a dict are really, really safe. If you run on Ion Python or Jython or some of the other pythons that people have created the GIL and the single bytecode of the time thing doesn't hold true and there's no guarantee that the underlying data types are going to be safe to use for multiple threads and even if they are safe to use for multiple threads without locking, there's no guarantee that any assumptions you've made about what's going to be atomic or not atomic are actually going to hold true. So one of the things I've found personally writing in Python code in the past is that when I moved to a new VM, I find bugs. I find bugs because I've made assumptions that don't actually hold true. Rust has all the type safety stuff of a strongly typed language but it also focuses on data races as kind of a primary thing. This evolved when Rust started, they had a particular vision and it changed and it changed and changed. What they've got now is a really good system with ownership and I'll talk more about that in a little bit. It's also really, really crazy fast. So there are a couple of routes you can take to fast. One is to have very abstract definitions of things and then compile it to a crazy back end that makes absolute sense for you. And there's some stuff out there EMPMR that was doing years ago with Pepsi-Cola and the steps system where they can compile high level representations and stuff that runs on your GPU and that's cool but no one's using it. Which is sad but reality. With Rust however, everything that's on the heap is clearly on the heap. Everything that's on the stack is clearly on the stack. So you can write programs that run entirely on the stack if you've got a problem that's amenable to that and not pay any overhead for heap allocation at all. Which is where that 11,000% difference and Fibonacci came from because it was making all the function calls on the stack. All the data was on the stack. There was no heap allocation at all for that program. Maybe there was a tiny little bit in the runtime at the beginning but there was none in the code that I had. One of the big differences that you'll run into is it's got explicit compilation. On the other hand, running talks to run your lints and your checks and your tests, we're almost at the point of explicit compilation in Python and to a degree I think we'd almost be better off by saying look, we're going to have that and make the I want to run a script without explicitly compiling it a special case or a wrapper. Like, is it go run? There's a thing... Yeah, there are things out there that can give you that with completely compiled languages because all of the people I know doing professional I'm writing lots of Python are actually working in a write code, run a command to compile-ish that does all these things. So it's not really that different. It doesn't have exceptions in the same way we have exceptions. So for us exceptions are a normal part of flow control and they're not exceptional, they're just a normal part of flow control which is weird to people who come from other languages and tell us how wrong we are. And I actually love this in Python, it's really elegant, it works quite well. Rust does have stack underwinding, so it has non-local returns and it's moved from being a thing that was really hard to get at to a thing where there's a supported contract rounder and you can use it. But it's not intended to be primary case flow control. It's intended to make sure you can clean up properly when a web server thread completely dies or something like that. What it does have is structured returns. So this is very similar to the go idiom. Who here has written stuff in go? Right, so enough in the room that's worth me describing this. So in go the idiom is that you return a value in an error as a tuple and you unpack that and you inspect it to see if an error actually could and then you manually return. And this is extremely tedious. Of all the things I can think of about go that I would like to love, that is like at the top, because if I could love that, there's so much more about go that I'd appreciate. So I'll come back to that, but structured returns are kind of this big thing. But the other big thing about Rust is that it's still really small. I say there's a lot to learn, but if you look at their RFCs, the list of things that they want to do to the compiler, to the language to make it more capable, it is huge. It's a really ambitious group. So what we've got right now is a good solid language. It's like this, but there's this whole space of stuff around that they want to enable and that the community is working on. So that's going to be really cool as that comes to fruition. So basic stuff about Rust. There is a single tool that formats Rust code into the standard thing. There is no debate about which way this should be configured. As you run it, your code's done. You'll move along with your life. It's got a package manager, kind of like Pip. It's called Cargo. Trying to write Rust code without using Cargo would be crazy. Don't try and do that. So this is a bigger set of code. So this is a... Now, why did I write this code? Oh, yeah. I wanted to just walk through some of the sort of things in Rust that really start to look different. So import statements are used. You break them into two. You say that you're going to use an external module by saying that the crate that you're going to use. And then you have a use statement which actually brings it into this particular namespace. So use standard colon colon itter gives me a symbol itter that I can use. The same as import thread.bar as bar would give me bar. So the default is that it just gives you the last component as your local symbol. The struct definition is equivalent to a class definition. That's giving me a thing called fib. It's got two ints in it. And I can access those through dot notation really easily. Implementation of fib says this is where I'm adding methods that I can call. And you'll note that it's completely detached from the actual definition of the structure of the data. This same syntax is used to implement traits to say I'm implementing a particular abstract base class. So it gives you consistency. They could have made that be part of the same struct and then the other one different. But this is... I like this. This function new here is equivalent to a static method because it's taking no parameters. Yes. I'm pretty sure I've got a slide on that, so we'll zoom back to that. This here is the actual way you construct one of the fibs. You just pass in the attribute and the value you want it to have. And you can use that directly, but it's an idiom to have a new method that takes whatever parameters you want and maybe massages them a little bit and gives you back the thing that you're going to use. Note that there's no return statement. Just like in Python, if you run off the end of a function, none gets returned. If you run off the end of a method here, the last evaluated thing, the last expression, gets returned. So you only see return when you're doing an early exit. And so that's actually a good visual thing. You can see, oh, we're exiting early and it really stands out more than it does in Python. So I kind of wish Python did this. Here, we're implementing a trait. So Tim's question before was, is it explicit? I'm saying that fib is something that you can iterate over. So I'm implementing the iter called an iterator trait and this trait needs two things implemented for it. It needs a type of the item that you're going to yield as you iterate. And that's going to be a U64 and it needs a next function which is mutable. So I'm mutating state when I iterate across this and it takes self. And it returns an option. So an option is an enum and it's kind of like a union type for folk who know type systems. For folk that don't, it's able to be either one of two... An enum can be one of many different things. Enums and rust can hold data. So they're not just mapping to C ints of 0, 1, 2, 3, 4, 5. They're actually able to carry data around like a struct themselves. This option one has two options, two values in the enum. One value is none, there's nothing there. And the other value is some with the data that is wrapping which in this case is the result. So what this lets you do is if you were thinking about pointers you could have a nil pointer and a value that you're pointing at. But we're doing this without dropping down the pointers. So the higher level in the system. So we can tell if there's something there or not and if there is something there we can pull it out and look at it. And so this is pretty simple. What else is there that we need to talk about? Let. In Python 3.5 you can use let. Is it let? No, it's just a assignment, isn't it? With a colon. So my brain is making mistakes. So you say let to declare a variable you're going to use that goes on the stack in the current function. Like I said stack and heap are absolutely clearly identified as being separate things. If you want to be able to change it you'd say let mute. And it's very similar to all of the C flavour set of languages. You can do pointers and references and everything else. You can put let expressions anywhere you want. They don't have to go at the beginning of a block or any sort of crazy restrictive thing like that. And note that we didn't inherit from iterator. This isn't iterator, but we have an inherited front. The type within next has been inferred. So the compiler has figured out all the types from the only information it's got is the structure itself and the parameters to the function. So I didn't need to use an explicit type there at all. Type inferencing across functions depends on explicit statements. Every function has to be explicitly typed and that's partly to do with the linking, but also in the Haskell community, the best practice there, even though the compiler can infer across the entire program, the best practice is to just be explicit of the function boundaries. It gives you better error messages, strength the problem space, at least should be clear about what you're doing. So they said straight from the get go that that's what they wanted. So inheritance. This up here, trait foo bar colon foo, is inheriting foo. The trait foo is going to be always present if you've got the trait bar. Wow, five minutes left. We are in trouble. So struct Baz here has an implementation of foo and an implementation of foo bar. If you don't have that line there, this would fail to compile. So even when you do inherit in a trait, you still have to explicitly implement each of the traits that are involved. It helps with reasoning. You can very clearly see what's going on. Safety. Baz is a struct and I assign it and now I try and use it. It's moved, I can't access it anymore. This isn't an attribute of the underlying data, so much as an attribute of the compiler. It knows what you have and haven't done. Under the hood, if you had two pointers from one name to another, the data that's pointed at won't have been moved. The bits of the pointer will have been moved, but you'll still get this error. This is involved in checking for safety in other ways as well. So this here says that you can't have multiple owners and making changes to a thing. If you want to have two people making changes to a dict, you've got to broker ownership to that dict somehow. Same for lists. The API is a bit weird to get your head around, but once you do, it really starts to make a lot of sense. The rules are you can have one mutable reference and no read-only references. You can't read from it if someone else is changing it. Write down at the machine level. Or you can have as many read references as you want, but no mutable references. The compiler enforces that and propagates it all around the system. The other thing you need to worry about is when you're calling into some data, it's sitting on the stack and you return back. If someone's taken a pointer to that data, they're now pointing into garbage land. This is a place where you can easily break things in C or C plus plus. So Rust is a lifetime concept. It says if you're trying to hand out a reference to something where the lifetime of that is going to be less than that place you're handing it to experts, it will error compile time. You won't find out at runtime. You'll never have that bug. So given we don't have time, I'm going to jump all around and not have any idea where we are in the slides. Right, yeah. So this is the exception stuff. And this is like, if you look at this file double example, I just took this out of the error, out of the book. There's a wonderful, wonderful book. That first line, letmute file equals try exclamation mark, file open path, matte error, client error I.O. There's a lot of noise there the first time you see it. But what this is doing that tries a macro and that result at the top there is a, it's another one of these enums, but instead of being an enum with none or some, it's an enum with an error code or a success value. So when you get it back you either have an error or you have the thing you wanted back. And the compiler can type course from the expression within that try into one of those two things and try will early return from your function with that error. So that is exactly the same as the go idiom in terms of the reliability of the code you get out, but with about one-tenth the boilerplate once you've got all your, your, your scaffolding for it set up. That particular expression in there is arbitrarily long to show mapping from options to results and a few other things that I thought I'd have time to talk about. I did time to talk, I swear to you. So this is the equivalent code in Python and down here this match is doing destructuring. So it's taking that structure of the data and this is why the structure of the data being separate of the code is so important. It can take the structure of the data and introspect it to give you back a whole bunch of things. So OKN is giving you the result value I was talking about and the error is giving you one of an enum of errors because it's unwrapped to get to your enum and then this is actually equivalent to accept IO accept par zero accept global catch on. And this is the machinery to implement that. Go and look at the slides are up on GitHub. So they want to do a bunch of things that will make it much closer to Python like direct language syntax for generators co-routines, futures, async, this stuff is happening right now incremental compilation is happening right now to make it a lot faster for big projects but there's a huge number of other things like I said the RFCs, this is the current plan features. Algorithms beat everything so once you go to a sensible implementation of Fibonacci see Python is still kind of slow but PyPy and Rust get right down to the nose however if you I know we've run out of time but if you call from within Python you can where are my slides right so there's stuff in there that you can look at for bindings I'm just looking for a there right so this is comparing a iterator versus calling up for a JSON RPC and JSON RPCs are slower but it's not terrible so my advice for binding is you've got to go down to your C data types that's what's going to happen so if you can just use a JSON RPC written in Rust if the overhead of calling is not compared to what you're going to get that's probably a lot easier to manage but you can do a pure extension module do we have any questions thanks for the talk if I want to write some sort of new green field project some sort of server and don't mind the sort of threading details go or Rust and why so if the question is between go and Rust I would say Rust because what I mentioned before the idiom in go for layering error handling is it makes your code about three times as long and that makes it harder to reason about the code it makes it harder to figure out where things have gone wrong and because essentially what you've got here in Rust is an error monad and it really makes composing functions from different domains with different error types really really easy there's a little bit of boilerplate involved but it's just about at the point you could put a macro around that and then you get type safety and ease of development so in terms of the other stuff the HTTP stacks, web servers those are in Rust and probably more mature in go but I think they're where they need to be for you to write pretty much anything these days and the languages what you get from the safety is much less oh I've got to go back and spend the engineering time fixing that bug it's going to be closer to correct the first time round so to my mind thinking from an engineering planning perspective saying look you know we'll go and build up a PostgreSQL module for example if one didn't exist would be a reasonable thing to do because you can be confident that once you've done that it's going to be rock solid and you're not going to spend a lot of slow bleeding actually maintaining it forever any other questions so over there about from that Rust isn't faster than Python what do you think the most powerful feature in Rust apart from that well I probably as I said I kind of got distracted by the stats and went down that path of the talk so I think the biggest thing about it is the influence of language features like the destructuring and the enums that carry data I really like those because they give you a very Haskell feel to it without all the overhead of having to go to a non procedural language so if I write three lines of code in Rust I know that they're going to execute those three lines of code if I write those three lines of code in Haskell they may or may not write them depending on whether or not they get evaluated and it becomes a lot harder to reason about it but a lot of the stuff that makes writing Haskell really powerful it comes from the type system and the destructuring and we've got both of those things in Rust so yeah that's sorry I can't they use the microphone oh sorry if compare Go and Rust like structs and beautiful designers on Go as well and if we compare these two which future of Rust wins well so look I don't think that you can really say win or lose for that sort of situation Go is a beautiful language except for the error handling stuff and if you like writing in Go great people are getting good results writing stuff in Go I think that the readability and the ability to comprehend what's going on in Rust is going to be stronger over time than it is in Go particularly as the features I was talking about like actual generators get added there's already channels it's just a module in Rust so you can write communication sequential process style IO things there's a futures thing in Knightly so you can do an equivalent to async IO and Rust can compile down some fairly large expressions down to a state machine for you and get really cool results that way so the over the next 6 to 12 months I wouldn't call them killer features but we're going to get the ability to write very easy to understand direct procedural code easy to reason about that compiles down to the absolute best possible way to implement that thing and that has been pulled out sideways through compiler plugins and extension modules If we've got time I didn't fully grasp the pointer part that you mentioned before does it essentially mean that you cannot have no pointer exemptions in Rust? No but you can have them in Python as well so right if you start with a language and you just write stuff in the safe language then it is I'd say it's impossible to get one of those exemptions if however you start writing unsafe code and there's actually an expression unsafe open curly bracket stuff and curly bracket but you're saying I'm going to step outside of the safety of the type system right now and I had slides that we kind of skipped over when you do foreign function interfaces and you call from Python into Rust Rust is going to have to not run its cleanup like if you're returning a struct back to Python Python is going to own that struct and you don't want to run your destructors but you don't want anyone else in the Rust space to think they own that struct either so you do an unsafe thing where you say to the system hey forget that you own about that and well it's actually that one's safe because of interesting reasons but when you come back and you say by the way I'm making a call on with that struct and this thing is actually a Rust source struct and it's owned by Rust or you want all the Rust safety to apply so at that point you do a very unsafe thing you say to Rust I'm going to tell you that this is a pointer to one of these things and I want you to own it so you cast it into that and that you have to wrap with unsafe and then after that all your normal Rust guarantees apply and then when you return it back you say memory forget it's owned by Python again all of which to say you have the ability to shoot yourself in the foot but you can do that in Python you can use the FFI or CFFI or an extension module to step outside of the bounds of the VM and break the thing if you do that you keep both pieces so I would say that what you want to do is you want to contain that make it as small as possible put it in a separate module test it really really really rigorously run fuzz testers everything you can think on on it and then all the stuff that uses it you can depend upon because the guarantees will be preserved by the type system okay so we've got time for just a couple more questions and there was a guy over here and here so we'll do those too and then any other questions you can talk to the speaker yeah I'm happy to hallway track I'm here and Barry and I we should pimp the sprints Barry and I are running sprints to get people developing on C Python so Monday Tuesday come along and any time I'm happy to talk about this and as the URL is there for the slides you've had lots of time to copy it down if you haven't I'm sorry get it from the video you mentioned early on that the rush communities made some really good decisions about building their community can you give some examples about what they might be and how they might be different to the way pythons done so one of the yeah so absolutely so one of the things they did is they sat down and talked about mailing lists versus kind of stack exchange style forums and so on and they have decided they decided a while ago now I wasn't involved in any of this so this is like second hand it's all been blogged about and so on they got rid of their mailing lists they have a stack exchange like thing you actual stack exchange I think for user questions and then there's a developer kind of lookalike thing where you discuss things that you want to build consensus around and then you have the issues in GitHub and you have ISC for real-time discussion so they don't have the mailing list kind of some of the patterns that occur in mailing lists don't occur elsewhere with people dog piling over a period of time they do on Twitter for example Twitter is like mailing lists where you take all the evil and you just amplify that so they went the other direction they said we want people to stop and think and we want to people who don't have any engagement in the community have to earn the ability to to comment in significant ways and you know and it seems to be working like they have a lovely community maybe that they just have three projects using it but I don't think that's the case because there are operating systems written in Rust entire kernel everything there's the server browser from Mozilla which is a replacement engine for Firefox that's gradually phasing in there's some really big things there are big open source projects being written in Rust this is the last question simple last question what does Rust do about object lifetime things like resource acquisition acquisition initialization control destruction what's the lifetime of objects do you have access to a destructor so I probably can't find it because I'll get in trouble so there is a drop trait if you implement the drop trait then you implement the function in it and that function runs when your object is going to be dropped yes so that will happen so there's always only one owner the type system guarantees that the drop trait will run in two places it will run when the thing goes out of scope that's when it runs if you wanted to make it go out of scope earlier you can drop on it directly which will make it go out of scope right away and the thing will be no doubt it won't try and run again it's not guaranteed that the drop trait will always run this is why I said earlier there's a thing that's actually safe if it runs unsafe because if you do like a long jump or something in a stack unwind you can get into situations where things won't run but in the normal course of stuff and if you're writing routine code it will always run so it's like there's this edge case and you have to be aware of it but by yeah don't do that alright thank you so much for speaking so can we all just give Rob a hand thank you