- So in this lesson,
we are going to dig deeper into Rust syntax.
And the first thing we need to do really
is to see how to declare variables.
So it turns out that Rust has integers and floating points
and strings and booleans and characters,
all the things you'd expect in a language.
The syntax for declaring variables
is a little bit different from what you might be used to
if you come from a background in C or C++ or Java.
So let's see what's available.
So first of all,
these are the signed into the types available in Rust.
So we have an i8, that's a signed eight bit integer.
So that would give you a value from -128 up to +127.
We have i16.
That would give you a signed integer from -32K up to +32K.
And then we have a 32 bit, 64 bit,
and 128 bit signed integers, negative or positive.
So obviously, the idea is that you'd use,
depending on the value that you wanna store,
you would choose a big enough integer to hold that value.
So these are signed integers.
Rust also has unsigned integers, unlike Java, really,
but like C and C++,
we have unsigned integers as well.
Same idea.
U8 is an eight bit unsigned integer.
That would give you a number between zero and 255.
U16, unsigned 16 bit.
That would give you a number between zero and 64K,
and so on.
Okay, so you could choose these types
for an unsigned quantity.
As well as the types we've just seen,
there are also two other types, isize and usize.
A signed integer and an unsigned integer
whose size is the same as the natural word
on your architecture.
So for example, my computer has an eight byte word,
that's the chip size.
So isize and usize on my machine would be eight bytes.
It's optimized for performance.
If you want to make an application as fast as possible,
then you should use these types
because those are the most efficient types
that your computer can can process.
Okay, so I feel like we should have an example
of all of this.
So for each section in each chapter,
I've got a separate demo.
Each demo is a separate Cargo project.
So I've got a Cargo project called lesson02_variables_types.
And in that Cargo project,
I've got various functions for each section of the lesson.
For this section, the function is called demo_integers.
So we'll have a look.
We'll open this project in a moment
and we'll have a look at this function.
And once we've had looked through the code,
then we'd run it using cargo run, okay?
And we'll do that for each section in each lesson
in the video series.
It'll be the same kind of pattern.
Okay, let's take a look.
So here is my rustdev lesson02_variables_types.
So lesson02_variables_types is a Cargo project.
I basically said cargo new lesson02_variables_types.
And it created this Cargo project.
If I open that project in Visual Studio Code
or whatever your editor happens to be,
this is what it looks like.
So the TOML file is pretty vanilla.
And then the source folder,
I've got a single file at the moment.
Later on, we'll see how you can write applications
with multiple files.
At the moment, it's just a single file.
And in here, I've got separate functions.
So each function starts with an fn keyword.
The main function chronologically
is the first function that will always be executed.
It doesn't matter the order
in which you write functions in Rust.
So this might be a surprise for a C++ developer.
In C++, you've gotta kind of declare a function
before you call it in the sequencing of your code.
So in C++, you might, at the top of your file,
have a function prototype
to declare the signature of the function
before you actually call it.
And Rust doesn't need that.
Basically, all the functions
within the same kind of namespace.
So the order that you write the functions in the file
completely irrelevant.
So chronologically,
I decided to put the main function first.
And at the moment, it's got calls to the other functions,
which I'll show you later on, but they're all commented out.
So I need to uncomment this function call
so that it'll actually invoke that function.
Let's take a look at that function, demo_integers.
Here we go.
So, obviously, this is a one-line comment.
Rust supports multi-line comments using a / and a *.
Okay, so that's the same kind of thing.
You could say, blah, blah, blah, end multi-line comment.
That's the same as most other languages.
So let me just revert.
Okay then, so what have I done here?
Then I've declared,
this is how you declare a variable in Rusty,
say let, followed by the name of the variable,
and then a :, and it's type, okay?
So that's different from what you might've seen
in other languages.
So for example, in Java or C++ or C#,
you just said something like a int x = 42,
you'd have the type of the variable, then it's name,
then it's value.
It's back to front in Rust.
Let is the variable declaration,
name of the variable, :, type.
So these are all 32 bit integers.
The first value is decimal and it's a signed quantity,
so I give it negative value.
The next value is hexadecimal.
0x is hexadecimal.
0o is octo.
If you like octo, I don't actually, but you might.
And then 0b is binary.
So there we go.
I've got four signed integers.
I've got an unsigned integer for a little bit of balance
and I've given it a positive value.
Incidentally, if you try to assign a negative value
to an unsigned integer, you're gonna get a compiler error,
which is what you'd expect.
And then I've got an isize variable.
I'm kind of curious to find out
how big is an isize on my machine.
Well, there's an isize variable,
and then I've printed various things out.
The println function is quite intuitive.
Really, curly brackets here is a placeholder.
So when it says curly brackets,
it'll grab the first parameter at the end, a1,
and it'll pass that value into here,
and then it'll grab the next parameter
and pass it into the next placeholder here,
and then it'll grab the next parameter
and pass it into this placeholder here.
So it basically fills up a1, a2, a3, a4,
and then b and c in the order that they appear here.
Or you can display them in a different order.
So here, technically speaking, this is parameter 0,
and that's parameter 1, parameter 2, parameter 3,
parameter 4, parameter 5.
But I've displayed them in a different order.
I've displayed parameter 0, which is that one at the end,
and then I've displayed parameter 1 before it, okay?
So actually, this print statement here,
when I call println this example,
it'll print the numbers in reverse order.
It'll print parameter 5 first, so that'll be c.
Then it'll print parameter 4, which is b, and so on.
And then finally, notice this syntax.
This is interesting syntax,
and I'm gonna explain it in more detail later on.
Effectively, stud::mem::size_of is a generic function.
You've gotta give it a type,
and it'll tell you how big that type is.
The way you call generic functions in Rust
is you say ::, and then inside angle brackets,
you give it the type that you are interested in.
So this is kind of similar
if you are coming from a C#, C++ background, I should say,
it's similar to same sizeof, something like that.
It'll give you the number of bytes of that quantity.
So when I run the application,
this will tell me how many bytes is an isize.
It's the natural word size on my machine,
which I think is eight bytes.
Okay, so let me just collapse the function down again.
When I run the application, it'll call main,
which will call my demo_integers.
So to run the application in Visual Studio Code,
I'm gonna open a terminal window
in the current directory, okay?
So the current folder, it'll open up a command prompt.
It's a PowerShell command prompt in Windows.
And in here, you can just say cargo run.
So it'll build the application and then run it.
Now an interesting, so first of all,
the output is as expected.
It output the numbers in kind of forward order.
Then it output the numbers in reverse order.
And then it told me that an isize is eight bytes
on my machine.
Okay, that's what I expected.
But also notice I've got some warnings here.
The Rust compiler is quite rigorous.
If you have functions that you've written
but you haven't actually called,
it'll give you a warning, and it has.
So it says you have a function called demo_floats
but you've never used it, okay?
So why did you write this function
if you're never calling it?
Did you forget to call it somewhere?
No, not yet.
It's just that I haven't got round to it.
This mechanism here, we'll talk about later on.
There are various different flags,
effectively a compiler flag that you can embed in your code
to influence the compilation process.
And what it's saying here is that by default,
the compiler is kind of running with this compiler flag.
It will gimme a warning on dead_code.
Code that exists, but is never called or used,
you'll get a warning for dead_code, okay?
You could disable that if you wanted to.
We'll talk more about that later on.
It's complaining about the demo_floats function
and the demo_other_simple_types function.
This one here.
And also the demo_additional_techniques function here, okay?
So in reality, obviously, you would be using these functions
and those warnings wouldn't exist.
Even though they were warnings,
the application still ran
and it output the information as expected.
Okay, so we've seen how to declare integers.
What we'll do in the next section
is see how to declare floats
and how do you use floating point values
in your application?