Devreal

Scale By The Bay 2019 UnConference: Sara Moore, Intro and Overview to Rust

Scale By The Bay 2019 UnConference: Sara Moore, Intro and Overview to Rust

Recording: Scale By The Bay 2019 UnConference: Sara Moore, Intro and Overview to Rust

this is just gonna be like a basic overview of rust and some of its like fun quirks and just kind of like an intro overall to the language and some fun things you can do with it so let's just kind of like dive right into the code that's the most interesting part so I have this main class with a grocery list function I'm going to I think I might have messed up my code just a second ago but I'm going to run this and prints out a bunch of errors and I how many items are in your list one just an apple and there we go my list has Apple in it so let's go look at that code and and and kind of break it down a little bit so we have items which we're declaring as mutable so that we can change it because in rust everything by default is immutable like so we've created these mutable structures and for example count that's like when the user enters in how many items are in their list we're passing a mutable reference to count and this function read line is then going to write to it so looking past that part I'm calling count trim trims the right whitespace parse turns it into a you size which this is kind of an interesting type so rust has a lot of different like integer types like pretty common with most languages however rust is like very explicit about it so this use size like if you asked for the length of a vector it would be au size and every index into a vector is also of type u size and under the hood it's just like some type of integer so the question is if you want to use a plain integer to index a vector do you need to like convert it or will it like infer the type Russ doesn't do type inference so I believe that if you just create like an integer or like an rest it would be like an i-32 or a 964 it would be like we can't use this to index an array and you would have to like convert it to a you size we could do some experimentation with that in a minute though so anyways this is just like basic some basic code that like goes through what the user is is telling us it's reading these items pushing them to a list and then at the end I'm printing them out I had this code which also like went through the list and printed them out in like a pretty way but this does the job it's kind of ugly but it's fine let's break down what this does a little bit though this is kind of interesting so this is a string formatter and you may have seen something like this in Python more like you know you have like a form an F string right and then these brackets which you actually put like variable names in however with rust the the brackets are like parameterised so like the first item goes into the first bracket and then this colon and question mark you guys ever seen anything like this before no so it's like I actually had to look it up today because it's something that I was just like copy and paste around and I was like what does this really mean it's essentially like a little mini map function that knows so like this mini map function this colon so like anything to the left of the colon would be like my argument and then anything to the right would be like do this with it so in this case we have like one argh and the question mark means print the debug flavor of whatever the items are so let me show you what would happen if I didn't have this so we run this and it at compile time it says a vector of strings cannot be formatted with the default formatter so basically rust is saying the rest compiler is saying I don't know how to print out a vector of strings so what we want it to do is for every item in this vector of strings print what like the the strings debug default is and debug is just like if I printed a string what would happen let's see how do you instantiate a string these are the types of so why did I choose five apple pear peach banana cherry yeah so you can just throw in a string literal a string literal interesting fact is an STR and it's not a like string yeah there's a difference however you can like go back and forth okay yeah so so this is like the super basic application example so there's like another level beyond this that might be a little interesting and I I implemented merge sort in rust and merge sort is one of the applications of rust where you're like this is probably not the greatest idea because merge sort if you remember merge sort is like okay you take an array you divided recursively until you have like one length lists and then you sort them as you like merge them back up the tree so there's a lot of like data copying going on so it's a little bit messy so this this version of the implementation is like the I'm not worrying about how much I'm copying data I don't care I'm going to be as inefficient as possible and then I have another merge in place where I'm trying to be a lot more efficient trying to reduce like do as few of copies as possible and that one is not currently working so but we can still like take a look like how it kind of works a little bit so basically so we have this merge sort function it calls merge sort recursive oh yeah I was going to show something interesting too let's call this merge sort function that is working so we are going to create a vector of strings and then we're going to call merge on my vector and let's just say for example that this function I know it takes a second parameter this is just for example let's say it also you need to pass in like the length of like how many elements is in your list like that's dumb you wouldn't need to do that but let's just say you do okay so there are a few interesting things to unpack here but let's just run this guy right here so this is the Baro checker at work so we just instantiate admire which is a vector and I'm using this like Veck exclamation mark which is a macro that instantiates a vector and then append all of these values to it so we have that we have a vector I pass it in as the first argument and then when I try it again the borrow checker is like but wait you don't own this anymore you just you know gave it to me this mergesort function so you can never use this ever again so these are the types of things as you're learning rust are so painful because you just have never had to think like this before like confusing about like how that like why like calling the function yeah so so the question is it's it's confusing especially because like the the method hasn't even been like evaluated yet right like we're still in the process of passing these arguments and and I think this is something similar to if you were at the the talk earlier today something similar to like if I assigned like anytime I even just like do a mini like assignment or anything like this like MIVEC no longer exists anymore and so yeah you you run into these like very confusing situations and when I actually saw this earlier today I was like what why like especially because what you just said like we haven't even called this function yet so like ownership like seemingly hasn't been passed yet but the baro checker is is able to be really smart sometimes smarter than you want it to be so like the horrible way to get around this is to just like clone it like okay like just pass a copy of it in and then yes it would not I'm guessing I could be wrong the question yes okay better that's sorry the question is if I were to put the clone on the second MIVEC versus the first will it succeed yeah guesses right like we lost control of it here so we're not going to be able to own it there oh that was my bad yep same problem yep so that works oh thanks yeah yeah so we're allowed to have as many readers as we want so yeah we're like allowed to read the data however we can only have one mutator at a time so that's like one instance where this is just a reader and this is this is the the mutator so I actually don't even use this parameter at all I just threw it in there and see you I could like you know make a good story but yeah if I wanted a reference I would put let's see I do that here in this append function I take a reference to a mutable BEC vector and there's a difference between an in rust there's a difference between a reference to a mutable vector and a mutable reference to a vector this is so like let me unpack it a little bit more a mutable reference to a vector says that you can like reassign right like like you could have read like a sign take this take this variable and assign it to like a whole new vector and then a reference to a mutable vector says that I can actually change the vector okay yeah so this is merge sort so we have this merge sort recursive function this is our base case like when the lists are only one length this is just computing the middle index and then the question was what is it about like list length that makes it not assume ownership and I really 100% don't 100% know the answer except that I presume it's really just like reading a property about the list and so that it really isn't like if it's not if you're not changing the data or mutating the data and you're only reading the data then there's no need for you to like take a mutation like I'm you like a reference to a mutable structure in yeah so these are the same function that we're looking at and this is merge which is this guy right here so this just takes like the left the right and then does all of this I probably I implemented this today I there's probably a better way to implement this but it's been a while since I have done it but but essentially you know you like do merge sort and then when you have like appended all of the left elements you just like push the right at the end because they're already sorted right like that's the shortcut you take and this function is like the only interesting function I feel like because new is the new array that we're building like the sorted array and so this is something we already kind of briefly looked at but append actually takes the right array and the right index and then just append everything on to the end of new so it actually like mutates new it doesn't like return a copy of new it mutates it in place and what's what's cool about this is is unlike other unlike other other programming languages like Python when you're calling this function you know just by looking at it but this function could potentially change your arguments right like you you can tell like okay right I don't care about right anymore I'm passing an ownership right index I don't care about that anymore I'm passing an ownership however this new thing that's being called like is sorry actually like changing this argument so that's like a safety feature I suppose I guess you know that it could change it because when you pass in this argument to append you know like you don't care about the first two things and if you just pass new without this running cargo check which just runs the bar Oh checker it says this function is asking for a immutable reference here you need to pass it and it knows that by looking at this method signature where it's asking for like a ref like mutable reference here did that answer your question about how do you know I mean there's no guarantees that it's changing it however like you're aware of the fact that so the question is how do you define a function that guarantees it will not mutate the parameters and the answer is exactly correct that merge this merge function does not mutate left and right because it can't like let's do a little experiment hopefully this will fail and I didn't just lie okay expected immutable reference found an integer maybe I'm using the wrong maybe I'm using the wrong function for a pent push yes append probably like a pens all the other elements of the vector so I mean we could what yes right so the compiler is like pretty smart however like you may or may not want to actually change it to mutable and like that's up to the programmer to be like oh I'm so glad that it caught me that I was just trying to mutate this and I really shouldn't be or to be like oh crap the Baro checker sucks I have to go and follow all these instructions but yeah there you go yeah yeah there's a difference between taking a reference and and a just like mutating mutation being able to mutate it so let's let's see if we can get this to work so I'm passing it in as mute a table I wonder if I also have to declare it as I probably also have to declare it as mute a table and I'm creating it append left not found in this scope what did I do expected a type thank you so like this variable is mutate a bowl not necessarily that the type is mutated all expected expression I thought let's see so maybe it will just know that left is mutate a bowl from here I feel like I'm hopping around really quickly so it's saying that this doesn't need to be mutated mutate a bowl which I think it's wrong hmm oh that's sorry that's an error because of this like here let me so when you import these modules this is just how you import functions from another file it it checks those files too and so because I'm not calling this in Maine it's like you're never calling this but it that worked so even if I don't make this variable mutate able if I pass it in and say that this function can mutate it that's enough which seems a little interesting to me I'll have to like look into why that is anyways we are way over time I like could talk about rust all day this is a super quick glance at my implementation in rust of something called tau which if you've never heard of it before is essentially a graph database that Facebook made like this is old news this paper was published like there tene and in 2013 but it's this graph database and so this is my implementation of it in rust if you're interested in learning or talking more about it like I'd love to chat it's also part of a paper that I was an author co-author of at OSD I last year which was essentially we built a multi-tenant data store in rust and it was really really fast so it was pretty cool [Applause] you