This is Hacker Public Radio Episode 3,681 from Monday the 12th of September 2022. Today's show is entitled, Rust1-01 Episode 3, functionally insane. It is part of the series programming 1-01. It is the tenth show of Black Colonel, and is about 41 minutes long. It carries an explicit flag. The summary is, in this episode, Black Colonel teaches you how to make functions and for loops in Rust. Hello and welcome to Hacker Public Radio. My name is Black Colonel and welcome to Episode 3 of Rust1-01. Now, you might have thought, the last episode might have been my final episode because it has been so long since I've recorded anything, but I've been moving and I've been changing jobs and I've been doing a lot of other stuff with life and I've kind of now in a somewhat stable situation, so I decided to record another episode and I got an interesting new audio setup and I'll go into that in a different episode, but for now we're making Rust programs, we're doing the Rust thing, we're programming and we're doing all that. I noticed that there was a couple of things that I kind of did poorly in the last episode, not really in the explanations, but more in what best practices were and stuff like that, as well as some things that I kind of just wanted to build upon. So in this episode, we're going to clean up our program to make it a little bit more in line with some best practices. We're going to create a function to take care of our actual dice rolling. And at the end of the episode, I'm going to try to get into a little bit of air handling and stuff like that. I might poke a little bit into where I'm hoping to go with this because I do have a long term plan for this series, but we'll see if we actually get there. Now, starting out with where we ended last time with our program, what we're going to do is first, I'm going to clean up a few of these things. So we made all of our variables here, U32s, unsigned 32 bit integers, which is basically fine and it works for our purposes. But there is a best practice in Rust, which is a thing where if you're doing unsigned integers, you can do U size, that's uniform, Sierra, India, Zulu, Echo, U size. And if you're doing signed integers, you can do I size. And what this does, it gets the default bit size of your integer for your architecture. So if you're using a 32 bit system, it'll be URI32 and if using 64 bits, it'll be URI 64. This is just kind of a best practice type of thing because it gives you the most bang for your buck and it allows you to kind of have a little bit of a different, you basically you don't have to worry about a lot of like Y2K type bugs as you upgrade systems because it'll automatically upgrade the bit size. Anyway, so we're going to start out by upgrading all of our U32s to U size, so that's the sum. As you size, the dice is U size, our parse is going to parse to U size, our size is going to parse, is going to be U size and we're going to parse to U size. Our cur die is going to be U size and that's all of our things. That's kind of what I should have done last time, but if I'm quite honest, I forgot U size existed. So that's on me. The next thing that we're going to do is actually we're going to change all of these to I size is because I want us to be able to handle negative values. Now, you might say, why do you want to handle negative values now when you didn't want to before, because now that we're kind of getting into the dice rolling thing, I think it's a good idea to be able to, in the future, we're going to be able to roll negative amounts of die rolls or be able to negatively add bonuses and I want it all to kind of be consistent. So I'm going to do that. I'm going to make everything into an I size. So for right now, it's not really going to matter because everything is sort of just adding them, but that's how I'm going to start. Next thing that we want to do, which might have been a good thing to do, start, but we're going to be thinking about how we're going to actually pop our function out of this. Now what we could do is just use the same loop structure that we have for and just preserve it in a function, but I'm actually going to use a couple of new rust techniques. I'm going to introduce a four loop. I'm going to introduce an underscore variable. I'm going to introduce the match statement and I think that's it for right now. So right above our FN main statement, we could do it below, but let's do it below. So at the end of your file, I gave you give yourself a couple of lines. Let's type in FN, Fox Trot November, Space, R-O-L, Romeo, Oscar Lima, Lima, and then an open parentheses. This is our function declaration. We're defining a function called role. Now we need to give it some arguments. The way that arguments work in Rust is they put in the argument name that'll be the variable name that you use in the function. A colon and then a type declaration for what that argument will be as the type. So we're going to have two arguments in this function. We're going to have num dice, colon, space, I size, comma, space, num, size, colon, space, I size, those parentheses. So as I mentioned last time, variable names, which these arguments are variables, are generally done in snake case. So that's num, num, num every uniform, mic, underscore dice, delta, india, charlie echo, and num size, num every uniform, mic, underscore, size, seri, india, delta, echo, sera. And then after our closed parentheses, we're going to do a space. Now we're going to need to give a return type because we want this to return what was our sum variable before. So we're going to do a minus sign and a greater than sign. So you get a little arrow looking thing with the dash and then triangle bracket, looks like a right arrow kind of, and then we're going to do another space and we're going to do I size, so india, sera, india, zulu, echo, and that's going to be the return type. So it's saying you take this function called roll, it's got two arguments num dice, which is an i size and num size, which is an i size, and it's going to return something of the type i size. So we're going to do a space and an open curly break it and then new line. That's how I like to do it anyway, that I'm going to do a tab and so now we're inside our function, and we're basically going to re implement the things that we did before. So the thing that we need to do first is we need to bind our random nuncher, random number generator. So we're going to do let space, mut, permutable, space, rng, space, equals, space thread, underscore rng, open parentheses, closed parentheses, semical. So this is the same line that we have at the top of our main function, well it's the second line of our main function, but you know you don't mean it's close to the top of our main function. And this is going to set up our random number generator, kind of give the default entropy and all that jazz, and we're going to do a new line, and we're going to get our sum variable in here, we're going to let mut, space sum, colon, space, i size, equals, zero, semical. And that's going to define our sum variable. I just realized I'm pretty sure that the type, I'm not going to say that totally a lot, I'm just going to leave that as a thought for now, we'll look it up later, we've already gone this far, not a port. So now we're in our roll function, I'm going to give ourselves another new line, and so we have our sum. So we have our number of dice, and they have a number of sides, and so now we need a roll these dice. And there's many different ways that we can do this, however, I'm going to use a statement called a match statement, because I think it's cool, it reminds me a lot of the case statement in bash, which is nice, and it's just a good thing to learn, because you will use it a lot in rust. So I'm going to do match mATCH space, and then num underscore dice, that's the variable you have to for, and then a space. And then an open bracket, open curly brace, and give ourselves some new lines. So what this statement does is it takes the variable that you give to the match statement, and it tries to match it to various cases. So the first case we want to look at is when the number of dice is positive, it's greater than zero. So on the next line, we're going to do num dice, space if space num dice is greater than zero. And that basically says, so this will match num dice, if num dice is greater than zero. So then we're going to do a space, then we're going to do an equal sign and a greater than sign, to give us another kind of like arrow looking thing. It's slightly different than the type declaration for return values. It can be confusing, but it's just something you have to get used to. So we're going to do a space, and this is what we're going to give what happens at this point. And it can be a single function, it can be a assignment for a variable, which we are going to do in a second, or it can be an entire block of code, and that's what we're going to do now. So we're going to do an open curly brace and a new line. Now we're going to do inside this code block, which is just this function, it's only going to run when num dice is greater than zero. I could have done this in an if else if statement, but I didn't want to, because that's boring, it's functionally equivalent. It's actually exactly the same, really, but I think this looks better and feel free to fight me in the comments. So what we're going to do is inside of this code block is going to be our four loop, or we've looped through the number of dice, and this is going to introduce an interesting thing in Rust, which is you can normally the compiler will yell at you if you don't use a variable, because it's like, hey, you have all this memory, it's just sitting there, it's not doing anything you should probably do something with it. But if you are just making a variable for an iterator or something like that, that you don't really use, then it's kind of stupid for it to yell at you for that. So what you can do is when you're writing your code, if you put an underscore at the beginning of the variable name, then Rust will know, oh, that's just some random thing that's not actually going to be used. I'll just leave it alone, and I'm not going to worry about that. So in this, what we're going to do is a four loop, and the way that the four loop is structured, and then I'll get into how it works, is the word for FOMR, Fox Trot Oscar Romeo, space, and then we're going to give it a iterator variable, which in this case is going to be underscore delta india echo, and then a space, and then the word in india november, and then a space, and then we're going to do the number one, and then two periods, then the equal sign, and then numdice are variable. And so this might look very familiar to you when we did the gen range thing and all that. But what this is basically saying is for whatever our iterator is in the range from one to the number of dice inclusive. So if we had a non-buseless iterator variable, we could use it in the four loop technically, we could still do that, but it wouldn't be recommended in the four loop. So at the first iteration, die would be equal to one, then it would be two, then it would be three all the way up to, and including the number of dice. So in this case, because we put that equal sign in there, it's going to include the end point, and that's what we want. So then we're going to do a space, and then we're going to do an open curly brace, and then new line, and then inside this four loop, what we're going to do is we're going to have, we're not going to worry about a current die or any of that stuff, we're just going to directly add two hours, some variable, so we're going to do some, and I'll show you how we're going to do that because it's kind of cool. So we're going to sum space plus equals, which is a thing that's in, I believe it's C plus plus, I know it's in Python, but it's a way of assigning a variable while adding to it. So if you did some plus equals one, it would redefine some as the value of some plus one, or in the last episode, if we did some plus equals cur die, then that would do the same thing, as our sum equals some plus cur die, but we don't have a cur die, so it might be asking how the hell are we going to get our randomness in here. We don't have a current die, and the answer is another match they missed, because we can put a match statement here in the assignment, which is really cool to me. So after that equals sign, the plus equals, we're going to do a space and then match and then another space, and then num underscore size, and then a space and then an open curly brace, and then some new lines, and then we're going to get inside this code block, and our first case is going to be num size, if num size is greater than zero, and we're going to do the equals sign, greater than sign, and then a space, and then RNG period, G, E, N, undurchs or range, gen range, an open parentheses, one, double dot equals num size, and then a comma at the end of all of that, because there's a comma separating each one of these match statements, which will come back to when we break out of all of this nonsense, so this got to look quite complicated, but just follow around, I'll try to walk you through it, and I'll re-walk you through it at the end, hopefully, if I don't forget, okay, then we're going to go to the next line, notice we didn't need to use curly braces or anything around the RNG gen range, because it's just that one function declaration. So on the next line, we're going to do num size, if num size is less than zero, and then we're going to do our equals greater than, and then a space, and then RNG dot gen range, and so this is something that we're going to use later in the four loop, when we do the negative num dice as well, but in this case, what we're going to do is we're going to our first part of our range is going to be our num size, because it's negative in this case, and then we're going to do the double dot, and then an equal sign, and then negative one. So this is going to take us from our negative num size all the way up to negative one, and that'll be our end of number range, which means that if we have a negative number of sides, then we'll end up with a negative number, a negative sign in front of whatever the diagonal is. So if we rolled one minus, or a one D minus six, then that'll give us a number from minus one to minus six, which can be useful. I mean, it's not always useful, but there are certain circumstances where it'll be useful to do this, and so I want to be able to make those circumstances possible. So then we're going to go to the next line, after the comma, after the closed parentheses, if I didn't say that, and then we're going to have num size space, if num size is double equal sign space zero. So if that's precisely equal to zero, this is the same thing that we used in the if statement. Last time to test if the loop num was equal to the dice, now we're going to do space equal sign greater than sign for that arrow, and then space. And then this is an interesting thing that you can do in, in rust. If you want to make absolutely sure, that your compiler knows what type you're giving to just some random number, you can actually just put it after the number. So if we do zero, I size. So that's zero, no space, no space between this. Zero, India, Sierra, India, Zulu, Echo, all as one word type of thing. Then if you use a syntax highlighter, it'll highlight it because that is a zero of type I size, and it's a specifically of that type. So there's no ambiguity there, and then we're going to do a comma after that. So you might say, okay, that's that's it. That's all we need for this batch statement. We're all done. We can close parentheses it or close curly bracket it and just be the, but rust's compiler will yell at you, because you need one more thing in all match statements, and that's anything else. Now I hear you crying in mathematics, though the well-ordering axiom states that a number can only be greater than equal to or less than any other, not those are the only three possibilities. But rust does not know the Zermelo-Frankle axioms. So, you know, we kind of have to just humor it here. So the way we do that is we do an underscore, and that just means if anything else happens, and for right now, if anything else happens, if it manages to break math, then we're going to space, we're going to do an equal sign greater than the other space, and we're just going to return a zero of type by size, because like that's not going to happen, and we're not going to worry about it, and then we're going to do a comma, and the new line, and then we're going to closing curly bracket, the numbersides match statement, and we're going to put a semicolon after it. That's important, because this is in an assignment, we need that semicolon, because it's not a full code block, it's a code block inside of another statement. All right, so then on the next line, we're going to do a curly, a closing curly bracket for our four loop, and then on the next line, we're going to do a closing curly bracket for our, if the number of, or if numdice is greater than zero statement, and then we're going to do a comma, because now we're going on to the next part of the numdice match statement, and then we're going to go onto a new line, and this is where we're going to say for numdice, if numdice is less than zero, so now if we have negative value for the number of dice, then we're going to do our equals greater than sign, and then an open curly bracket, and then a new line, and then, if I was using strict, best practices here, or rather, if I was using best practices for 1965, which is what my dad taught me, a rule of thumb that he gave me is that if you ever write code twice, it should be a function, and if your code goes over a page, it should be a new file. It's kind of a good rule of thumb, I wouldn't take it too seriously, but it's like a good thing to keep in mind, and if I were doing that, maybe I would want this to be a function, however, there actually are some differences, so that would actually be more complicated, so I'm just going to write it again. So now I'm going to do another for loop, so for underscore die, and now we're going to do numdice double dot minus one, or equals minus one, because now we're in the negative dice dimension, that we're going to do space in an open curly breaks, and then on a new line, we're going to do some announced that of plus equals, we're going to do minus equals, and then a space, and then our match statement, and then num side, and then an open curly brace, and now we're just going to copy basically everything that happened before. So on the next line, we're going to have num sides, if num sides, greater than zero, and then our equals greater than RNG dot gen range, one double dot, or open parentheses, one double dot equals num sides, close parentheses comma, and then the next line num sides, if num sides, less than zero equals greater than sign RNG dot gen range, parentheses, num sides, double dot, or equals negative one, close parentheses comma, new line num sides, if num side, it's equal to zero double equal space equals greater than zero i size comma, and then our underscore statement of anything else, if it breaks math, just return to zero five size, probably should you do something more dramatic, but you know, it doesn't have to. So then next line, closing curly brace, semi-colon, for that, some minus equal statement, and then on the next line, closing curly bracket for our four statement, so now that we've finished off our two statements, for if it's less than or equal to zero, the number of dice, now we're going to go down to the next line, close the less than zero num dice statement with the curly brace, and we're going to go to comma, we're going to go to the next line, and now it's going to be our num dice, if num dice is double equal to zero, and space, then our equals greater than sign, and we don't actually need a block for this one, because if it's equal to zero, we're just going to return a zero i size, because if there's no number of dice, then there's nothing to do with some. I could have it just return some, yeah, now let's, let's stay consistent and have it return some here, then we'll do a comma after return some. Next line, everyone should know it by now. We're going to need to have our everything else under score statement, because math doesn't exist in this universe, I guess. Then a space, and then an equals greater than sign, and another space, and we're just going to return some, if we break that, and then a comma, and then on the next line, we're going to close our match statement with a curly brace, and then we're going to go to next couple lines, and then we're going to return some at the end. All right, and then a semicolon. So this, after we go to the next line, it closes curly brace, the function, this is our function in its entirety. So basically, if I run through the way that this function operates, you're going to put into it a number of dice in some integer, 32-bit, or 64-bit, probably 64-bit, but some integer, and some number of sides. The first thing on the first line of this program is going to do is initialize the random number channel rate with some entropy stuff. Next thing it's going to do is it's going to allocate that sum variable of type i size, and it's going to initialize it to zero. So we have that variable ready to go, ready to use, and it's mutable, which is important. So next what we're going to do is we're going to take that num dice argument that we were given, and we're going to look at what it is. It's going to check if it's greater than zero. It's going to check if it's less than zero. It's going to stack, it check if it's equal to zero. And if it's none of those things, it's just going to return the sum, which at this point is zero. So if it's greater than zero though, it's going to go into that four loop. It's going to go into a four loop for each number from one to the number of dice we gave it. It's going to add a random number based on the number of sides we gave it. In this case it's going to add, if that number of sides we gave it this positive, it's going to add that positive random number from one to that number of sides. If it's number of sides we gave it this negative. It's going to add from the number of sides we gave it to negative one. And if we gave it If it is zero number of sides, it's going to add zero to that sum. And then if the number of sides we gave it is some kind of El Dritra Balmination of Mathematics, it's going to ignore that El Dritra Balmination. It's not going to call to get a fethel's model or anything. It's just going to calmly return zero. That's what it's going to do. And the next after it iterates through all of that, however many times, it's going to pop out of the match statement and return that sum with all of that juicy total of dice given to it. Then instead the number of dice we gave it were negative, it's going to iterate through for those dice from the number of dice we gave it to negative one. So that same magnitude of range. And then it's going to subtract from our sum of a random number depending on the number of sides we gave it. We gave it a positive number of sides. It's going to subtract a positive random number from one to the number of sides. If we give it a negative number of sides, it's going to subtract a negative number from the number of sides we gave it to negative one. And an important note here is that if both of them are negative, it's going to actually end up with a positive result because it's going to subtract the negative which is going to be a positive. It's going to add instead of subtracting, which is kind of cool. And might be useful probably not, probably really not. But it won't break anything and it's an interesting sort of mathematical easter egg, if you will. If the number of sides we give it a zero, it's just going to add nothing to the we'll subtract nothing technically. Or add negative zero depending on how you want to look at it. And if it breaks math, it won't call the goes to pull air dash, it's just going to calmly return zero. And then after it iterates through that loop, it'll return the sum, because it'll break out of that match statement. If instead the number of dice we give it a zero, if we tell it to give us like zero d6, it's just going to return the sum which at this point is zero. And if it breaks math in some other way, if the number of dice is that eldritch numerical abomination, then it's going to just calmly return sum, which at this point is zero. And that's our whole function. That's what our function does. So now if we go up into our main program, our main function here, we can remove this RNG declaration, this RNG mutable RNG variable declaration. And we can remove this mutable sum declaration. We will keep the dice in the side's declaration as well as the arc's declaration, so it'll be important. We're going to remove all of this loop, the loop num, the print for the dice, and the new line print the backslash n. We're going to remove all of those lines. So the next line we're going to have is just that total line. And instead of having the total line return the variable sum, since as you can probably see some does not exist in this scope, we're going to remove that the SUM out of that. And instead we're going to have it return Romio Oster, Lima, Lima, open parentheses, and then dice comma, space, size, dis, so that's the two variables that are holding our arguments from the command line. So dice inside, it's actually put just singular side and then a close parentheses or that roll declaration. And so what that'll be is that that'll take the two arguments we gave it, put it through our function, and then pop it back on that total line. So if I save this file and then I go into our rest 101 directory, the project folder. So that's the place that contains our source folder, our cargo.tomble and everything else. And I run cargo space, run space, double hyphen, space, one space six. So if you remember from the last episode, it's going to compile our program it's going to run our program and then that double hyphen is bash interpretation for that's all we're doing with this function. And then we're going to add in these extra arguments to the next things. This is going to give the one in the six as arguments to our program that we're writing to this should roll 1, d6, 1, 6 sided dot. If I hit enter, it's going to fetch down the crates because this is a new computer that I haven't done this before on. It's fetching the random number crate from the interwebs. And it is still fetching because I did all of this on my laptop, which means it isn't pre downloaded, which means it takes a while because compiling takes a while and downloading also takes a while. So I'm just feeling dead air now until this thing finishes. It'll go faster every other time because the already be on my computer. And there it goes. So it's now downloaded all of the random dependencies as well as the random thing that's compiling all of it. And when you look at that, I don't know how to spell I got an error. Cannot find value for numb sizes in this scope. That size is Sierra, India, Sierra, Echo Sierra because I don't know how to spell sides apparently. Sierra, India, Delta, Echo Sierra. So that's just me being a spelling monstrosity. So I clear that and I run the same thing again, cargo run double hyphen, space one, space six. Then I get a one as the output. Wow, which look at that. Oh, I can totally tell that this is working. So I'm going to do the same thing cargo space run, space double hyphen, space one. And this time I'm going to do space 100. And we got a 67 at the end, total colon 60 seven. We're going to run it again. We get an 89. We're going to run it again. We get a 69. Nice. Now I'm going to do 22 to make sure that we get both the upper and lower bound. Got two, got a two, got a one, got a two. I'm going to give it a zero as one of the options. I'm going to do one in a zero. I'm going to give a zero. Then it could do a zero on one and I get a zero. I'm going to do a negative one and a two and I get a negative one. And if I do it again, I get a negative two. I'm going to do a negative one space negative two and I get a positive two as the answer. So it all looks like it's running smoothly. It's running very well. So there's a couple of things that I want to do more in this video, but I can feel my voice starting to go. I have not been drinking enough water and I don't have very much water in front of me. So I'm going to call this episode here. I'm going to continue next time with some some more fine tuning of this function. I want it to return a vector of di-rolls rather than the total. That way we can do the total separately and maintain all of our di-rolls in case we want to do something with that. I want to go into more of air handling. Because I have touched on that very much yet. But for now, I think that this is enough new information and interesting information to sort of say she the rust miss for now. Because I think that rust is super interesting and super cool programming language. And I think that match statement, the way it handles ranges, being able to embed a match statement in a function declaration, or a function assignment is super cool. Concept of I size is a super cool thing that I forgot completely existed last time. But yeah, that's about it. Feel free to contact me on MasterDone. I'm black kernel at next net. Thoughts social emailed me at IzzyLeabwithSupium.me. Yeah, just contacts me with all of the ways that I have in the description. Hopefully, I actually write show notes for this episode because one I am tired and two. I apparently don't know how to write HTML. But anyway, that's it for now, and I'll see you next time. You have been listening to Hecker Public Radio at Hecker Public Radio.org. Today's show was contributed by a HBR this night like yourself. If you ever thought of recording podcast, you click on our contribute link to find out how easy it means. Hosting for HBR has been kindly provided by an onsthost.com. The internet archive and our synced.net. On the satellite stages, today's show is released on our Creative Commons. Attribution for.0 international license.