190 lines
5.7 KiB
Markdown
190 lines
5.7 KiB
Markdown
#Rust
|
|
|
|
The quick brown fox jumps over the lazy dog. The dog stays blissfully asleep. :)
|
|
|
|
# What is Chapter 3?
|
|
Chapter three is about common programming concepts that I would be familiar with
|
|
from other languages. This chapter covers variables, mutability, data types,
|
|
functions, comments, and control flow.
|
|
|
|
# 3.1 Variables and Mutability
|
|
## Variables
|
|
Rust defines variables kind of like C does:
|
|
```rust
|
|
let x = 7; // x is 7!
|
|
```
|
|
but Rust also allows explicit declaration of types when defining a variable:
|
|
|
|
```rust
|
|
let x: u32 = 7; // x is a 32 bit unsigned integer with value 7
|
|
let y: f32 = 7.0; // y is a 32 bit float with value of 7.0
|
|
```
|
|
|
|
Variables can be defined in specific scopes that do not escape the inner scope:
|
|
|
|
```rust
|
|
let x: u32 = 4;
|
|
{
|
|
let mut x = x;
|
|
x += 2;
|
|
}
|
|
|
|
println!("{x}")
|
|
>> 4 // NOT 6.
|
|
```
|
|
|
|
## Mutability
|
|
All variables in Rust are immutable unless specifically mentioned. This is
|
|
part of ensuring memory safety--you will not be able to overwrite variables
|
|
unless you declare that they can change over time. Here's an example:
|
|
|
|
```rust
|
|
let x: u32 = 2;
|
|
x += 2; // Will fail. x is not mutable
|
|
|
|
let mut y: u32 = 2;
|
|
y += 2; // Will work, since y is mutable
|
|
```
|
|
|
|
### Constants
|
|
Constants are a special case in Rust. They are immutable variables just like
|
|
`let`, but they have a special ability to be defined in the global scope,
|
|
where `let` may not be. Here's an example.
|
|
|
|
```rust
|
|
const TWO_PLUS_THREE: u32 = 2 + 3;
|
|
fn main() {
|
|
println!("{TWO_PLUS_THREE}");
|
|
}
|
|
>> 5
|
|
```
|
|
Constants are by convention written in UPPER_CAMEL_CASE.
|
|
|
|
# 3.2 Data Types
|
|
Rust is a statically typed language. Variables in Rust must have their types
|
|
known at compile time, or else the compilation will fail. A lot of times types
|
|
can be inferred, but this is not possible for cases where there are multiple
|
|
possible types.
|
|
|
|
For these cases, the type must be annotated, like this:
|
|
```rust
|
|
let annotated: str = "This one is annotated!";
|
|
let not_annotated = "This one is not!";
|
|
```
|
|
|
|
## Scalar Types
|
|
Scalar types are those that only take on one object. Examples in Rust are
|
|
integers, characters, booleans, and floating-point numbers.
|
|
|
|
Integers can be signed or unsigned, with different levels of bit resolution,
|
|
up to 128 bits. That being said, there is an 'arch' length that is the size of
|
|
the operating system. This is used with `isize` and `usize`. Signed integers are
|
|
stored with two's complement.
|
|
|
|
Numbers can also be written in differnet formats, including decimals (with _
|
|
escapes), hex values, octal values, binary values, or even as a byte(b'A').
|
|
|
|
>[!note] A special note about *integer overflow*.
|
|
> Rust code compiled and ran in debug mode will have checks for integer
|
|
> overflow, causing the code to panic at runtime if an overflow occurs.
|
|
> Production code compiled with the `--release` flag will NOT panic however,
|
|
> but instead will wrap around to the first value in the possible range.
|
|
|
|
# 3.3 Functions
|
|
Rust functions have a couple of interesting properties:
|
|
|
|
1. Rust functions don't care about order. They can be in any place in the code,
|
|
as long as the scope of things is maintained relative to where calls happen.
|
|
|
|
2. Functions start with `fn`, followed by a name in snake case, then inputs,
|
|
then the function scope using {}.
|
|
|
|
*functions* is an example of some basic functions
|
|
|
|
## Parameters
|
|
Parameters can be used to pass values into functions. When this is done, two
|
|
things must happen: First, the value must be input into the function (duh!).
|
|
Second, the function must *match the type defined in the function*.
|
|
|
|
Arguments are a similar thing to parameters, but have a technical difference
|
|
that arguments are concrete values. Like add(5), vs add(x).
|
|
|
|
## Statements and Expressions
|
|
A *statement* is a line of code that does some computation or other calculation,
|
|
and does NOT return a value.
|
|
|
|
A *expression* evaluates to a resultant value.
|
|
|
|
Rust does something interesting. When defining a variable, the output is a
|
|
*statement*, not an expression. Using `let` to define the variable does NOT
|
|
return the variable itself. Defining functions are also statements.
|
|
|
|
Calling functions, macros, or using a scope block created with curly brackets
|
|
is an expression however. Here's a mind bending example:
|
|
|
|
```Rust
|
|
fn main() {
|
|
let y = {
|
|
let x = 3;
|
|
x + 1
|
|
};
|
|
|
|
println!("The value of y is: {y}");
|
|
}
|
|
```
|
|
|
|
This is an statement (defining main), with a statement inside (defining y) which
|
|
has an expression inside (the statement defining x, and then the expression adding x).
|
|
|
|
>[!Important] Statements, Expressions, and Semicolons
|
|
> Notice `x+1` does **not** end in a semicolon. If it did, it would be a statement.
|
|
> Expressions do not end in semicolons.
|
|
|
|
## Functions with Return Values
|
|
Functions can have outputs, but they do not need to be defined with `return` keywords.
|
|
Instead, the function will by default return the last expressions result.
|
|
|
|
Functions must declare the type of the output:
|
|
|
|
```Rust
|
|
fn five() -> i32{
|
|
5
|
|
}
|
|
```
|
|
|
|
|
|
# 3.4 Comments
|
|
|
|
This one is pretty simple.
|
|
```Rust
|
|
// This is a single line comment.
|
|
let x = 22; // They can be after code
|
|
|
|
/* Or, if I've really got something to say
|
|
I can use this multiple line comment */
|
|
|
|
```
|
|
|
|
# 3.5 Control Flow
|
|
## `if` Statements
|
|
If statements in Rust are expressions, that optionally have else and else if
|
|
statements.
|
|
|
|
```Rust
|
|
if number > 5 {
|
|
println!("Yay!")
|
|
} else if number < 4{
|
|
println!("Boo!")
|
|
} else {
|
|
println!("Just right!")
|
|
}
|
|
```
|
|
Conditions for if statements *must* return Boolean types.
|
|
|
|
## Repetition with Loops
|
|
To do loops in Rust, there are three main keywords for loops: `loop`, `while`, and
|
|
`for`. `loop`s will loop infinitely until a `break` statement is triggered,
|
|
`while` operates while a condition is true, and `for` loops through a specific
|
|
number of iterations.
|
|
|