Episode: 3519
Title: HPR3519: Rust 101: Episode 2 - Rolling With the Errors
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr3519/hpr3519.mp3
Transcribed: 2025-10-25 00:55:47

---

This is Haka Public Radio Episode 3519 for the first day the 27th of January 2022.
Today's show is entitled, Rust 101, Episode 2 rolling with the errors and is part of
the series, programming 101, it is hosted by Black Colonel and is about 54 minutes long
and carries an explicit flag. The summary is in this episode, Black Colonel helps you construct
a simple dice rolling application in Rust.
Hello and welcome to Haka Public Radio. My name is Black Colonel and this is Episode 2 of my
tutorial on Rust. In this episode I'm going to be taking you from the Hello World default
program that gets created when you create a new program with cargo that I went over with last
time and I'm going to take you from that to a fully functional dice rolling application.
It's not going to be anything fancy at this stage but in this episode I'm going to go over how
to use external crates so those are crates which do not come pre-installed with Rust so not
in the standard library of Rust. I'm going to show you how to use a standard crate which actually
it's going to be in that order because the standard crate that we're going to be using is a slightly
more esoteric than the external crate that we're going to be using because the external crate is
the random library that we're going to be needing to roll dice. I'm also just going to go over how to
do variable declarations, loops and a couple of other things. Now I'm not going to be getting into
well I'm going to be getting into if statements but I'm not going to be getting into for loops or
while loops because I kind of think that those might be, I mean first of all the syntax of them
are just based on the same syntax as an if statement. So once you know how to write an if statement
you can pretty confidently go into especially while loops and for loops aren't that complicated
if you're familiar with other for loops but if you're not familiar with programming in general
both of those can get pretty complicated as far as from a logical perspective and Rust has this
concept of just a loop which is an infinite loop. You can think of it like a while true in most
languages like you can do a while true in C or you can do it in bash even and that's kind of what
it is but it's just a infinite loop that's just loop and then you break out of the loop when you
want to break out of the loop. That's what I'm going to be using in this particular example for
simplicity as well as just to show off that functionality of Rust because I think it's really cool.
So to get started we're going to we have the hello world program right here and I'm just going
to start out with making I think I went over this in the last episode but it's been a while so I
don't actually know what we're going to do is we're going to change this so instead of printing hello
world it's going to be printing out a variable specifically I'm going to use the variable for the
total of all of the dice that we're going to end up rolling so I'm going to replace the hello
world with total TOTAL a colon and a space and then an open curly brace and a closing curly.
And what this is is if you've ever used the print f statement in bash or in C or any of those
languages this will be kind of familiar as a as in the syntax that this how this works which is
you put in a some kind of marker token and then it will replace that token with the variables you
put afterwards in order and how it does that is if you ever used a bash with like an echo and then
a double quote and you want to put a variable inside of that double code just inserted into the
middle of the string you can put a dollar sign in front of the name of the variable it kind of
does a similar thing but it's a little bit more flexible and a little bit more general so we'll
have the opening and closing curly braces and then after the closing double quote we're going to
put a comma a space and the name of the variable that I'm going to use here is some or SUM because
it's going to be the sum of all of the dice rolls later on but for right now it's just a variable
so you could call it anything that's just what I'm using here so the way that this is going to work
is whatever value we give to some it's going to take that value and replace the opening closing
braces that little token it's going to replace it with the value that's in some you can get a
lot more complicated with this formatting style in Rust but for right now that's all we're going to
be using it so then before this line we need to define what sum is so I'm just going to do a simple
declaration for now so right before that line I'm going to put let LET space and then the name of
our variable in which in this case is some SUM and I'm going to do I mentioned that you don't have
to do this when I was talking about just stuff in Rust in general I believe in episode zero
but I'm going to make explicit type declarations just for ease of reading just so that you know
what everything is so I'm going to put a colon after the name of the variable a space and I'm going
to put U32 which is an unsigned integer that is 32 bits which can get very large because it takes
all of the same amount of memory as a 32 bit integer so it takes one 32 by bit of memory but it
doesn't use negative numbers so you can just keep making it as big as you want you get double the
amount of space as you would with a signed integer that's the same bit so you can get much bigger
positive numbers with a U32 then you can with an i32 but you're limited to only having positive
numbers so this wouldn't work for negative numbers or any of that kind of stuff but since we're
using this as a sum of dice rules we're not really expecting to get a negative value out of it
at least not in the way that I'm doing it right now which is not involving the fudge dice or
anything that involves negatives in that way and I'm going to put a space an equal sign a space
and then a zero and then a semicolon so we're going to assign this the value of zero to start with
and then we're going to add to it later but right now this is what we're what we got
going to save this file and I'm going to run it just with if you are in the the project folder so
in this case I'm using the name rust roller for this project if you're in that project folder
you can type in cargo space run and it will compile and run the program I believe I went over
this before but that's how we're going to be testing it at each stage so what we're expecting
to get out this is sort of I know this isn't really about specifically this is a programming
thing in general but one of the first things about programming is debugging and going through
it step by step like this will aid you in debugging because the first rule of debugging is to know
what you're expecting to get out and then when you test it you compare what you expected to what
you got and then you try to figure out if something went wrong how it went wrong from that point
so right now we're expecting for it to just for it to print out total colon space zero because
that brace that double brace thing is going to be replaced with the value of some which in this
case is zero so I'm going to run cargo.run and we get total space zero which is exactly what we
were expecting so everything is good at this state so now we have something which can print out our
some variable so now we need it to actually generate a random number and to start out with this
we're going to be doing a single random number from one to two to start out with just to make
sure that we can do we can get that down before we move on to the next step this is sort of building
on what we already have at each stage because then if something goes wrong we can pinpoint
exactly the change where it went wrong this is some basic troubleshooting stuff but I think it's
good to go over it in case there's anyone who hasn't really been exposed to basic troubleshooting
or basic programming concepts before it and I just find it useful to refresh even for people who
are familiar with it so you understand more of what exactly is the thought process behind the
debugging rather than just sort of going on instinct or something like that because it can be a
little bit dangerous to do that so in order to import our random library we're going to go into
the project folder there's a file called cargo.tommel which is cargo with a capital C
.tango oscar mic lemma t o m l and this file we got two headings we have package and dependencies
they're both in square brackets in the package heading we have the name of the of the project which
in this case is rust roller we have the version of the package in which in this case is 0.1.0 which
is the default that it gives to the very first instance of the package and you have the addition
which in this case is 2021 this is the addition of the version of rust that you're using because
they've changed the syntax and stuff in each addition so this will make sure that the compiler knows
what addition it should be comparing it to so that it knows what's an error and what is in
so knows what syntax to be using all that kind of stuff and then under that you have the dependencies
heading and this is where you're going to add whatever external crates you're going to be using
this is something I really really really like about rust because it has its own package manager
in cargo when you make a library you can upload it to cargo you can upload it to well I guess it's
crates.io technically but you can upload it to this place that is connected to the whole cargo
ecosystem you can write documentation which is has a standard form which goes on to docs.rs
which allows you to find documentation for the crates really easily which is really nice
and it allows for you to utilize those packages very very seamlessly within a rust program which
I'm going to be showing you a second but right now all we need to do is underneath the dependencies
heading we're going to type in rand that's Romeo alpha november delta space equals space double
quote and then zero dot eight dot zero and then a closing double quotes now that's the version of
this particular package that we're going to be using I believe this is the latest version
but you can put any other version number as long as you're familiar with like the way that it works
because it's going to be drawing on that version specifically now just going to take a brief aside
here because I think this is really cool if you go to docs.rs that's delta oscar Charlie Sierra
dot Romeo Sierra you put a slash you put the name of the crate which in this case is rand
then you put a slash and you put the version that you're using of that crate which in this case
is zero dot eight dot zero then you hit enter you're going to be taken to the documentation for that
crate and for that version of that crate which will give you all of the module structures traits
functions et cetera whatever's in there for that crate to give you a sense of how to use that
crate which is really nice because if you end up using an old version or crater if you end up
having to maintain legacy code using an older version of a particular crate you'll still be able
to access the documentation for that version until you get a chance to update it which is it's
just beautiful in my opinion it's one of the things that's just it's so nice to be able to have
that we've basically finished importing it as far as what we need from the cargo dot tommel so let's
go back into our main dot rs and above the main function declaration above that fn dot or fn space
main going to give myself a couple of lines and we're just going to type in use that's uniform
Sierra echo space and then the name of the crate which in this case is rand so that's going to be
Romeo alpha november delta and then we're going to put two collins that's colon colon and then
we're going to put a opening curly brace and we can put in here it's going to be a comma separated
list of the things that we want to import from this particular crate in this case what we're
going to be importing is the function thread range and the trait range so a common convention
in rust is that if you have a function or a variable that spans multiple words you'll use what's
called snake case which means that everything is lowercase and the words are separated by underscores
and if you have traits or classes or any of those higher level structures then they will be in
camel case I believe they might still be in they start with a capital letter that's that's all
I'm trying to say they if it starts the capital letter it's probably a trait or a class or a
struct or something like that and if it's snake case then it's probably a function or a variable
that's sort of the way that they separate things in rust parlance so in this case we're going to have
the function thread range which is going to be the word thread all over case an underscore
and then rng which is Romeo november gulf I'm going to put a comma and then a space and then
I'm going to do a capital r capital Romeo lowercase n lowercase g this is the trait range which is
used by the function thread range and that's why we need to import it we're not actually going to
be using it directly in this example so at this point we can use the function thread range or the
trait range in this program so within our main function at the very top above the above the
sum declaration I'm going to put let space and then it's I'm going to put in a mute which is an
MUT mic uniform tango because we need this variable to be mutable because it's going to be random
as as we're using it it's going to be changing so it needs to be mutable and then we're going to put
a space and then we're going to put um rng a lowercase in this case you can put whatever name you
want for this but because it's the it's the range that we're going to be using or the random
number generator that we're going to be using um that's sort of the uh parlance that it makes
sense to use so it's going to be the rng the random number generator and we're going to set this
equal to the function thread range so that's thread underscore rng and I know I keep saying range
even though it's supposed to be random number generator it's a bad habit that I've gotten into a lot
but whenever I say range I mean random number generator I think basically oh no because there's
actually the word range coming up so I'm going to try in the future of this to specify rng versus
range because I know that the rng is random number generator it's just a little bit more difficult
to say random or rng set of range even though they mean totally different sorry about that um
so we have this rng now this random number generator uh and what we're going to be doing for this
is we're going to be generating a number in this case I'm for this example it's going to be from one
to two because it's easy to see if it's working if you have a very small range because you won't
be getting the same number over and over again it'll be a 50-50 chance of getting the same number
I mean I guess it would be better if it was a larger range now that I'm thinking about it because
then it'll change a lot more over a larger range so you know what I'm going to change the what I
have here to between one and a hundred because why not um so we'll be able to see if it changes more
often um which will aid us because if we keep getting the same number we don't know if it's working
or if it's just giving us the same number over and over again so after our some declaration
right now it's set to zero because we haven't added anything to it now now we're going to
essentially roll a die we're going to get our first die which in this case I'm going to be calling
our current die because later on we're going to be rolling more dice so I'm going to start the
declaration with a let le that's uh Lima echo tango space current or c-u-r is what I'm going to
be using that's charlie uniform Romeo underscore die di it's delta india echo and then a colon
and space uniform 32 because this is also going to be a 32 bit unsigned integer because it's not
possible at the moment for us to be rolling a negative value then we're going to put an equal
sign a space then we're going to put lowercase rng that's a reference to our variable that is
assigned to thread rng we're going to put a period a dot and then we're going to put in gen that's
gulf echo november for generate and then underscore range the word range that's Romeo alpha november
gulf echo a open parenthesis and then this will be the range that we want to generate over which in
this case is going to be one to one hundred inclusive you can do exclusive or inclusive range in
this particular random random library which is something I really in I really like because it's
useful to have flexibility there so we're going to be doing it inclusively so that the numbers
can be right more easily and make more sense so we're going to do a one and then a double period
that's dot dot and then an equal sign and then the number one hundred so this is going to be a range
from one to one hundred including one hundred at the end and then a closing closing parenthesis
and a semicolon so what this is going to be doing it's going to be generating a range from one to
one hundred including one hundred and including one because it includes the lower bound
always and it's going to be generating our rng it's going to take it's going to generate a random
number with the random number generator from that range and feed it into our current die variable
and since we're not using any negative numbers in the range we know it's not going to be negative
so we can use an unsigned 32-bit integer to basically have more memory efficiency because it's more
efficient if we're not going to be using any negative values to use an unsigned integer technically
I could use like an 8-bit unsigned integer if I wanted to because I don't think that this I mean
one to one hundred is definitely not going to be above a 8-bit integer our 8-bit unsigned integer
but we're going to be making this user modifiable later so this is a lot of the user to get larger
numbers if they so wish although if they're rolling dice for that large of numbers for a tabletop
RPG or something then you know may whatever god have mercy on those players or the god forbid the
DM so now we have a die that has been rolled but we haven't added it to our sum yet so that's
the next thing that we're going to do after our current die declaration we're going to type in
the word sum which is our variable and then a space and then equals and then a space and then
sum so we're going to add whatever the current value of sum is to it and then add to it so plus
and then a space and then CUR underscore DIE that's Charlie uniform Romeo underscore Delta
India echo which is the name of our current die variable and then we're going to end that line
with a semicolon so this will take whatever the current value of sum is add the current die value
to that value of sum and make that the new value of sum this is going to be useful for when we put
in the loop to add more dice but for now it's just going to be adding whatever the current die is
to zero which is going to be whatever the current die value is anyway and then we're going to output
that sum which is going to be whatever the die value is because this original value of sum is zero
so it's already all going to work correctly it's a little bit bloated at this point just because
we're going through multiple steps but those multiple steps will help us later when we're adding
more complexity to it it's also broken down a lot more simply so that we can follow the way that
the values are changing throughout the program so now it should give us a value from one to 100
and including 100 so we're going to save this and we're going to run cargo dot or cargo run
from the project folder and I get an error why do I have an error oh so I only got one error
here says error expected semicolon found keyword function it says that the error is in my main.rs
file line three position one so this was not intentional it also gives underneath that it gives
the actual lot like it gives a little code snippet and it says it has the use rand double colon
open curly brace thread underscore rng comma rng with capital R close curly brace and then
underneath that it says in blue it says expected semicolon so the problem if that wasn't already
clear is I forgot to put a semicolon at the end of my use statement at the beginning of the program
so it freaked out but you can see this is one of the reasons also that I really like rust because
the output of the compiler tells you exactly what the problem is and you don't got to look through
very much to find out what happened there so that was what the problem was I'll just save the
program again I will do that and then I will run cargo run again I got another I got another error
which if you read the comments for the last episode errors are very common in rust just because
it has a very strict compiler which is very good because the compiler is also very good and will
tell you what the hell the problem is and the problem in this case it says cannot assign twice
to a mutable variable sum now from that I already know what the problem is it gives me more
descriptions afterwards as well as a helpline which says consider making this binding mutable
mute sum instead of just sum it is absolutely correct so when I define sum I just defined it as a
static variable a immutable variable but I also edited it later I added current die to it which
you can't do if it's not mutable so I'm going to change that line from let sum u32 equals zero
to let space and then mic uniform tango space sum colon u32 equals zero so I'm going to add that
little mute keyword right before sum now we'll make it mutable which will allow me to edit it later
and then I'll save this and then I'll clear that and I'll run cargo run again and this time it
works I get a value of 33 for my total I'm going to try it again to see if it's gives me a random one
each time this time I got 70 one more time I got 99 so I'm going to run it a couple more times to
make sure that I can get well actually if I wanted to now I'm going to change the 100 here to a two
so now it's going to read let curd diet u32 equal rng dot gen range one to equal sign two so
what that's going to be is I'm going to be checking now to make sure that it's possible to get a
value of two because now I know it gives me different values every time because the 100 was
large enough that I could see that it gave me different values at all every time but I never
got a value of 100 out of it so now I need to make sure that it is including the end point so I
changed the 100 to two so that it's more likely that I will get that endpoint and then I'll know if
it's including that endpoint or if something is going wrong deeper in the program that I can't see
this is useful if you have a much larger project just to double check to make sure that everything
that you're expecting to happen actually happens that way you're not surprised by bugs later on
so I'm going to save this and then I'm going to cargo run I got one going to run it again I got one
going to run it again I got a two so since I got a two I know that it is including that endpoint
because there's no way I would be able to get it to if it didn't include that endpoint so we're
good to continue the next thing that we're going to be working on is the is to make it user editable
to make sure that the user can put in whatever value they want into the command line arguments so
that it can roll a bunch of different types of dice and for this we're going to be using the ENV
the echo november victor crate from the standard library and what this is is that it provides a lot
of environment information to rust and this is environment information independent of operating
systems so this will give you environment information from Linux Mac and windows if you care
about that I don't I only use Linux because I think it's the best operating system but if you
use windows this will be the same thing because it is cross platform in the way that you write the
code which is very nice in a few ways especially for tutorials like this so underneath our use
line we're going to put use space STD that Sierra Tango Delta double colon ENV echo november victor
and then I'm going to remember to put the semicolon at the end of the line this time and this will
import that environment information into our program and now right before our RNG variable
declaration the let mute RNG equal thread range line right before that line I'm going to put let
space args that's alpha Romeo Gulf Sierra colon space and this is the type declaration it's going
to be a capital V capital victor echo charlie that's vec for vector and then I'm going to put an
opening pointy brace open triangle bracket then a capital Sierra T lowercase T RNG so that's
the word string with a capital S and then a closing pointy bracket and then I'm going to put a space
equals and then a space and then echo november victor ENV double colon alpha Romeo Gulf Sierra args
open parentheses close parentheses dot collect the word collect that's Charlie Oscar Lima Lima echo
Charlie Tango and then a double sees an opening and a closing parenthesis and a semicolon to end
that line so what this is doing is it's from that environment from that environment variable
that ENV it's going to be calling the function args which is going to grab all of the arguments
from the command line and then it's going to collect them using the collect method into a
container that you've specified with the function duck or with the variable declaration and this
case it's going to collect them into a vector of string so each one of the command line arguments
is going to be a string in that vector I'm going to show you how to call items from a vector
a little bit later as we're when we use this but it kind of works very similarly to bash where the
zero the zero with element of that array in bash or this vector in rust is going to be the name of
the program then the first element is going to be first command line argument in the second
element is going to be second command line argument etc a vector in rust by the way is a
it's basically like an array in bash where it's I'm trying to think of the equivalent in I mean
it's like a vector in C as well where you can if you make it mutable it doesn't have a defined
size at compile time it has a defined size at runtime so you can have multiple different sizes of
them and it'll handle all of that dynamically which is useful in something like this where you
don't know how many arguments you're going to be getting it'll collect all of them and put
them into a container that is accessible at runtime the downside of this is that it'll compile fine
but if people put in things that are weird it will break and you'll end up with a like a core
dump type thing I'm blanking on the name of that particular error but it's basically it'll crash
and you won't get a whole lot of information out of it until you debug that software so it'll
just essentially crash without saying anything you can put in checks for those crashes into your
program to catch those in case you're worried about that but because this is just a simple program
I'm not going to worry about going into that heavy of detail here and we're just going to use it
as is and you know we're not we're not going to put in or we're not going to try to call
the 30 second or I mean in this case we're not even going to call the second element yet of the
vector because we don't know if it's going to exist yet for right now we're just going to be putting
in one command line argument which is going to define the number of sides of the single dice that
we're going to be rolling right now all right I'm going to add a couple of new lines into this
document it up specifically I'm adding them underneath the mute rng line and the some line
because it divides my main function into a couple of blocks we have all of the stuff that is
essentially system level with the args and the rng which is stuff that happens outside of the
program that initialize that needs to be initialize in order for this program to work then we have
the stuff that I'm defining for this program so a the stuff that is going to actually be used in
this program that I have underneath that the stuff that is actually being changed in this program
like the current dice and all that kind of stuff so underneath the sum declaration I'm going to
put let and I'm thinking about the mutability of it now because I got that error for the sum but
this doesn't need so I'm going to put let sides that Sierra India Delta Echo let side then Sierra
so let sides plural colon uniform 32 space equals so this is a variable called sides that is an
unsigned 32 bit integer I'm going to put args which is the name of that variable we did that's
that vector of strings that holds all of the command line arguments I'm going to put a square bracket
and I'm going to put the number one because we want the first element of that particular vector
it's the same way that you it's the same way that you index or raise in python or in
bash or any of those you just put the number of the index in square bracket then we're going to put
a dot then we're going to put the word parse that's papa alpha Romeo Sierra Echo we're going to put
two colons a open triangle brace you three two closed triangle brace dot unwrap that's uniform
november whiskey Romeo alpha papa then an open and closed parenthesis and a semicolon so what
this is doing is you're getting the first element of our args which is that first command line argument
and we're going to we know that's a string so we need to parse that string in a particular way
so that we can get a number out of it and not just character because the reason why this important
is because in your computer system all everything is just being stored as numbers but like the letter
a a lowercase letter a is like the number 42 or something like that I think it's 47 I could look
it up but I'm care right now but if we have an a that we're getting from a from our command line
argument we don't want it to take it as 42 or if like the number one that one I'm actually going
to look up because it'll useful for this particular discussion of why this matters look up the
ASCII table because it is inclusive in unicode which is what rust uses natively so let's see the
numeral one the numeral one has value has a hex value of 31 or a decimal value of 49 so let's say
we wanted to for some reason I'm actually going to use a four let's say we're casting magic missile
so we're going to want to roll a d4 for that magic missile for the damage if we put a four in
there and we just ask it to use that for from the string and we just want to shove that into our
the number of sides that we want it's not going to put it as four sides because since it's has
that string of four that string of four to the computer is the number 52 so we're actually going
to be rolling a 52 sided die instead of a four sided die which is not what we want so we want it
to parse that string that number four string and we want to parse that as a four not as a four
not as a 52 so to do that we use the parse function in rust which will take that string and interpret it
based on the based on what the string looks like rather than what the computer thinks that is
essentially it's just minusing what is it it's minusing whatever it needs to minus in order to
get the actual value of what that number looks like rather than what it thinks it is just based on
what it's what the number is that's being stored in memory is that would might might have been a
little bit complicated but I think it that made sense but that's the reason why you need to parse
things from strings to numbers rather than just asking it to handle the string natively because
the computer doesn't know what the heck a string is all it knows is numbers while we were doing that
aside I think I noticed that I screwed up yeah because I needed to add after the triangle brace
u32 and then a closing triangle brace after that second triangle brace I need to add an open
and closing parentheses because it's a function that we're calling here now the double colon thing
that's in the middle there with the triangle brace nonsense that's a particular way of declaring
what type we're giving this function because there's a lot of different ways of
one of the biggest most important things about rust is that it is statically so at each stage the
program needs to know what the heck is going on when it comes to the type it will infer as much as
it can but it always the program itself always needs to know and if there's ambiguity you need to
tell it because otherwise it won't assume if there's more than one option so in this case the parse
function can parse it into different types of numbers so we could parse it to an integer
an i8 or an i32 we could parse it into an unsigned integer like a u8 or in this case a u32 in this
case we wanted to give us a u32 out of it so to do that we put that double colon and we put the
type in triangular braces and then we put the double parentheses that open and closing parentheses
to actually call that function so after all of that is done after that parse function is called
we have a technically we have a result with a u32 in now what a result is in rust i mentioned
this earlier in the series is it is a essentially a boolean with information inside of it so in this
case it'll tell us if if the parse function succeeded or failed and if it failed at this point we
could catch that failure and we could display something on the screen to say hey you just put in
you just put the letter a in this into this and you want me to parse this as a number and I don't
know what the heck that means so I just threw an error and you can catch that and say hey you put
a letter in here what is wrong with you in this case we're going to be smart about how what we
input so we're just going to unwrap it willing nilly which will if it succeeds it'll unwrap it and
give us that the value of that u32 that's in the success but if it's a failure the failure doesn't
have a u32 in it so if it's a failure it's just going to crash kind of anonymously it's it gives
us a little bit of information but it'll I mean it'll say that it failed to unwrap this particular
line which will tell us where the problem is which is enough in this case but we're going to be
we're going to be smart about how we input things so we shouldn't fail this but if we were trying
to put this into a user base we probably would want to let the user know that where the actual problem
is we're not going to worry about that right now but that's the whole point of the why that's
worded the way it is because we're unwrapping whatever we get out of it sort of willy nilly and we
don't really mind if it crashes at runtime because the user screwed up and so after that gets unwrapped
that's going to be a unsigned 32 bit integer because that's how we parsed it and it'll feed that
unsigned 32 bit integer that was the value that we gave to the command line argument that first
command line argument that's what that's going to be it's going to feed that into sides that variable
and now it's in sides we still haven't called sides for anything so what we're going to do is in the
declaration for our current die when we're rolling that current die we're going to change that
equals two that we have to equals sides so it's going to be equal Sierra India delta echo Sierra
and then the closing parentheses and then the semicolon and what that's going to do is rather than
going from one to two or one to 100 like we did before it's going to go from one to the number of
sides including the number of sides so it's basically the same as rolling a 1d whatever the number
of sides are and now we're going to save the program and this should work but the way that we
need to call it because we've been using cargo run which doesn't allow you to or rather we've
been using cargo run and then just hitting enter because everything was built in but now we need
to actually provide it with an argument if we just run cargo run right now it's going to say
that it panicked so this is sort of one of the things that we were talking about or we're not
being very safe with how we're writing the code necessarily because there are a lot of places
where things could break but it'll break at runtime and it won't break at compile times right
now we just gave it a zero argument so all that's in there but then we called the first argument
but we didn't give it any argument so it says thread main panicked at index out of bound the
lenn is one but the index is one and then it gives us the file which in this case is source slash
main dot rs gives us the line number and it gives us the character character number of the
actual problem um so in this case if we go to line nine and we go to character number 32 or 22
rather uh it's probably there okay so we got a character 22 that's right before the word
args in that line and the reason is because we called args at the index of one which is the second
element but the length of args is only one it only has one value which is the zero with element so
we tried to call something outside of its range so it panicked um but that's because we didn't
provide it with any arguments so we didn't actually do anything wrong in writing the code we did
something wrong in running the code which is why didn't yell at us in the compiler only at when
we were running it now the way we add command line arguments to cargo run is we do cargo space run
and then space and then two hyphens two little dashes and what this does if you're familiar with
bash is that says that this is the end of our first program like this is the last um like this is
the last thing you need to parse for the command line arguments for this function so this is saying
cargo you're done you've gotten all of the command line arguments that you need and now we're going
to be giving the command line arguments for the function that is about to run which is our function
or the rust roller function so then we're going to put a space after the double hyphen and we're
going to put 100 because we're going to roll 1d100 in this case to make sure that it can give us
different numbers every time we roll it and then we're going to hit enter and now it doesn't panic
it gives us a total of 34 and now we're going to run it again and it gives us a total of three
I'm going to run it again and it gives us a total of 71 so now we know we're getting different numbers
that are all between the range of 1 to 100 which is what we gave it as the upper bound now without
changing anything in our code I'm going to do cargo run double hyphen and then the number 2 and
now gives us a total of 1 gives us a total of 1 and then on the third time running it it gives us
a total of 2 so now we know that it's keeping it between those two ranges I'm going to run it
a couple more times gives us a total of 1 and a total of 1 again and so it hasn't given us anything
outside of that range of 1 to 2 including 2 and that's what we want so now we have something which
can roll 1 die from 1 to a given number of side but what we really want is for a to roll multiple
dice at whatever side count that we want so what we're going to do now is we're going to entry loop
which is going to roll a die in each iteration of the loop and then add those dice up I'm also going
to have it display what the die rolls were for each individual dice because that can also be
useful and also I want to so that's what I'm going to do so underneath our sides declaration that's
let sides u32 equal underneath that we're going to put let that's a Lima echo tango dice that's
Delta India Charlie echo then a colon and then a space and then u32 because we're not going to
have a negative number of dice equal and then a space and then we're going to put args actually
this is a good point this is where we need to decide on how we want the syntax of our command to go
I want to do it so the first number is the number of dice we're rolling and the second number
is the number of sides that way it corresponds to dnd notation of like 3d6 or 45 which isn't a real
dice number but whatever so I'm actually going to change this line I'm going to copy this line
and I'm going to paste it underneath the let mute sum u32 equal line so it's right before our
sides declaration that way it makes more sense when we're reading it because we're going to call
that the number of dice is going to be args square bracket one closed square bracket the whole line
right now reads let dice colon u32 equal args open square bracket one closed square bracket
and then we're going to put dot parse double colon triangle bracket u32 close triangle bracket
open and close parentheses dot unwrap open and close parentheses semicolon now we're going to change
the let sides line to be args two instead of args one because that's going to be the second command
line argument is going to be the number of sides so right now it should work as far as how we
had it before but we would need to put like some filler number for the number of dice because we
haven't actually used that yet so now right before our current dice I'm going to actually start building
the structure of the loop that we're going to the first thing I'm going to have it do I'm going to
have it print the word dice so I'm going to have print exclamation points this is a macro called
print and then opening parentheses and then a double quote and then the word dice and then a
colon and then a space so it's going to print out the word dice a colon in a space the reason I'm
doing this is because each time it loops I'm going to have it put what the current value of the
die was so to list out all of the dice values and then in a line under it a list what the total is
of those dice values so at the end of that line I'm going to put a semicolon and a new line
and now I'm going to need a variable a mutable variable that will keep track of what loop number
were on you could use i for this for like an iterator I mean you could do this in a actual for loop
if you wanted to or a while loop if you wanted to I'm going to be using a general loop but we still
need a way of keeping track of what loop number were on so I'm going to put let mute that's let space
mic uniform tango space loop underscore num space equals space zero semicolon I don't really care
what type of number it designs to this one so I'm not going to worry about a type declaration for
this one because it's just going to be whatever zero it wants to put there then on the next line
after the semicolon I'm going to put the word loop now this will create an infinite loop between
two curly braces so loop open curly brace close curly break um then in between those curly
brace I'm going to do some new lines so that I have it inside of the loop there the first line
of the loop so underneath the loop open curly brace I'm going to put an if statement the way if
statement what's working rust is you put the word if and then you put the conditional without any
parentheses or anything around it and then you put the scope of the if statement in curly braces
so in this case we'll put the word if that's India Foxtrot space loop num that's that variable
we just defined as zero before so if loop num and then a space and then a double equal sign this
is because a single equal sign is assignment it'll assign a value to a variable whereas a double
equal sign is comparison so it's comparing is this value equal to that value if it is it'll return
true if it's not it'll return false so basically if it is true that this loop num is space equal
to dice which is going to be the number of dice that we want to roll that's the variable we just
defined earlier as being equal to the first argument of our argument vector of strings and so what
we're saying in this conditional is if the loop number that we're on is the same as the number
of dice we want to roll because we're going to be having one loop per die and so if we're at the
last die meaning it's equal to the number of dice that we were supposed to roll since we're starting
at zero dice if that's true then I'm going to do a opening curly brace and then a space and then
the word break that's bravo Romeo echo alpha kilo and then a semicolon and then a space and then
a closing curly brace and we do not need a semicolon at the after the curly brace because it's
scoped so since it knows that the curly braces define a scope the closing curly brace implies
a semicolon you can put a semicolon there I believe but you don't need to put a semicolon there
so I'm not going to and then I'm going to put in a new line so that line is basically going to say
if we're on the last loop if the loop number is equal to the number of dice we were supposed to roll
since we're rolling one die per loop then you can break out of the loop and it'll go right to the
closing curly brace of that loop declaration you can see that this is very similar to a while loop
if we were doing a while loop num is less than dice would be kind of the same thing or it's even
more similar to an until loop in languages that have an until loop so we could say until the loop
number is equal to the dice then we can do this thing but I'm this is more of just a general loop
and a way of breaking out of that loop given a can do which I think is a little easier to understand
and so therefore I think it's a little bit better for this sort of simple level of program so
then on the next line underneath that if statement I'm going to put our current die declaration
I'm actually going to just copy and paste it from what we had earlier so I'm going to paste that
underneath that if declaration just wholesale because we want to do exactly the same thing we're
going to roll a die from one to the number of sides that's it and then the next thing that we
want to do is we want to print that out so we're going to print exclamation points that's the
print macro note not the print line macro because the print line macro will add a new line
character and we don't want to add a new line care and we're going to put an open quote
a open curly brace a closing curly brace and a closing double quote sorry
oh we're actually going to put a space right after that closing curly brace so the whole thing
in between the double quotes is going to be a open double quote curly brace close curly brace
space close double quote and what this is going to do is it's going to separate each one of the
die rolls by a space then we're going to put a comma a space and then a then CUR underscore DIE
which is the current die variable that we defined in the previous line and then we're going to have
a closing parentheses and a semicolon so what this is going to do is we already have it printing
without a new line the word dice and then it's going to have a space separated list of the dice
that we roll then we're going to go on to a new line and we're going to put in that
the some aggregator that line that we have below this where it says some equals some plus
curdye or the current dice we're going to take that line there we're going to
we're going to copy it or cut it and paste it right underneath that print statement so it's
going to take whatever the value of some is which at the first loop is going to be zero but on
each loop is going to be the sum of all of the dice we've rolled so far so it's going to sum up
all of those dice and we're going to add to it whatever the current die roll is to add to that die
so that way we get this running total of all of the dice that we're rolling and then underneath
that line we're going to put loop num that's our thing which is keeping track that variable that's
keeping track of what loop number we're on space equals loop num plus so we're going to add one
to the loop number because we finished this loop and now it's going on to the next loop
so we're going to add one to that value what this is going to do is it's going to loop through
rolling a die at every point and then adding that die to the sum variable creating an aggregate
of all of the dice rolls for each loop with one loop per die that we defined arguments so at this
point we can we can have it roll 3d6 46 3d10 whatever you want but we need one more line to make it
readable so after the loop num equals loop num plus one line after that line we're going to put a
closing curly brace to close out our loop and then underneath that line we're going to put
print exclamation point parenthesis open parenthesis open quote and then backslash which is
a escape character for a new line character and then a closing double quote a closing parenthesis
and a semi and what this is going to do is going to create a new line after it's written out all
of the dice and then it will have that print line exclamation point open parenthesis total space
double curly brace comma sum which will put out what the sum is of all of those dice roll so
now I'm going to save this project and then I'm going to cargo run and then I'm going to have it
roll 1d100 so I'm going to do 1 space 100 after the double hyphen so it's cargo space run space
double hyphen space 1 space 100 and I'm going to hit enter and it says dice colon 58 total colon 50
so it only rolled one dice or one die so it only has one element in the dice column and the total
is equal to that one die that it rolled so that worked well I'm going to run it one more time
and we got a different number so we know that the random number is still working it rolled a 55
so the dice colon 55 total colon 50 so now I'm going to have it do two space 100 so it's cargo run
double hyphen space 2 space 100 I'm going to hit enter and now it says dice colon space 21 space 26
and the total is 47 so you get both of the die values and their total which is what we're looking
for here because now for example if you wanted to do I mean I'm going to use this as an example
if you're playing backgammon if anybody knows how to play backgammon you roll 2d6 but you can use
either the total or each one of the dice individually to move various tokens so what you can do
here is if I do cargo run space double hyphen space 2 space 6 then it'll roll 2d6 and we have
five and a six on each die for a total of 11 so now if I'm playing backgammon I know that I can
either move two tokens one by five and one by six or I can move one token by 11 and I know that
just at a glance because I have both the dice values as well as their total can also be used in
other things as well but this is sort of this is the culmination of everything that I wanted to
and so now we have our nice little dice rolling application I'm going to clean it up a little bit
with a couple of new lines just to make it a little bit more readable and I should probably add
comments to this but I'm not going to because I have this entire episode explaining how I wrote
each one of the lines in this code and I'm going to put that in the read me file for the
get repository so it should all work out um this is basically the end of this episode and if there's
anything you need to want me to explain to you more that isn't clear uh give me a message on
mastodon I'm uh at black kernel at nixnet.social I believe uh it'll also be in the show notes for this
episode or you can email me at easy leboits at pm.me and that'll also go to my email and we can
talk about it um think that's about it so thank you for listening and I will talk to you next time
where what we're going to be doing is we're going to be taking this dice roller and beautifying it
making it a little bit easier to use on the command line as well as making it able to handle
advantage drop the lowest for like 46 drop lowest stuff like that just kind of like adding more
functionality to this solar program uh I'll talk to you next time
you've been listening to hecker public radio at heckerpublicradio.org today's show was contributed by
an hbr listener like yourself if you ever thought of recording a podcast then click on our
contributing to find out how easy it really is hosting for hbr this kindly provided by
an honest host.com the internet archive and our sync.net unless otherwise stated today's show
is released under creative commons, attribution, share-like, slid-o-licence
