😎Common Programming Concepts
Common programming concepts in Rust
Variable
Declare a variable
💡 Rust will infer the type of a variable based on the value we provide
Immutability
💡 In Rust, variables are immutable by default. If we want to make a variable mutable, we have to use mut
keyword before the variable.
Shadowing
💡 When the variables have the same name, and they’re within the same scope, the second variable will shadow the first variable.
The different between mutability and shadowing is that with mutability, you’re modifying a single variable, while with shadowing, you’re create two separate variables, and one of them is shadowing the other.
Scopes
💡 In Rust, variables live within a scope, which is the area between an opening and closing curly braces. The inner scope has access to the variables defined in the outer scope.
Because the outer scope can’t access the variable in the inner scope, therefore, we’ll get an error when we’re trying to access the variable in the inner scope from the outer scope.
Data Types
💡 Every value in Rust is of a certain data type, which tells Rust what kind of data is being specified so it knows how to work with that data.
💡 Rust is a statically typed language
, which means that it must know the types of all variables at compile time. In cases when many types are possible, we must add a type annotation.
Scalar Types
i8
, i16
, i32
, i64
, i128
Signed integers
1, 2, 4, 8, 16 bytes
u8
, u16
, u32
, u64
, u128
Unsigned integers
1, 2, 4, 8, 16 bytes
f32
, f64
Floating-point numbers
4, 8 bytes
char
Character (Unicode scalar value)
4 bytes
bool
Boolean value (true or false)
1 byte
Compound Types
Array
Fixed-size collection of elements of the same type
Varies depending on element type and size
Slice
Dynamically sized view into an underlying array
Same as underlying array
Tuple
Fixed-size collection of elements of potentially different types
Varies depending on element types
Struct
User-defined composite data type with named fields
Varies depending on field types
Enum
User-defined type representing a set of variants
Varies depending on variant types
Reference Types
&T
Reference to a value of type T
8 bytes
&mut T
Mutable reference to a value of type T
8 bytes
Other Types
Option<T>
Represents an optional value of type T, can be Some(value) or None
8 bytes (includes 1 byte for discriminant)
Result<T, E>
Represents the outcome of an operation, either Ok(value) or Err(error)
16 bytes (includes 1 byte for discriminant)
Notes:
The size of some data types may vary depending on the target architecture (32-bit vs. 64-bit).
Rust has additional data types like
raw pointers
,functions
, andclosures
, which are more advanced and not covered in this basic table.
Scalar Types
💡 A scalar
type represents a single value. Rust has 4 scalar types: integers
, floating-point numbers
, Booleans
, and characters
.
Compound Types
💡 Compound types can group multiple values into one type. Rust has two primitive compound types: tuples
and arrays
.
Constants
💡 In Rust, constants provide a mechanism to define fixed values during compilation. These values are immutable, meaning they cannot be changed after initialization. This immutability ensures program predictability and avoids accidental modifications.
Key Characteristics of Constants:
Immutability: The defining characteristic of constants is their unchangeable nature. Once assigned a value, a constant cannot be modified throughout the program's execution.
Explicit Type Annotation: Unlike variables where the compiler can infer the type based on the assigned value, constants require explicit type declaration. This improves code clarity and avoids potential type mismatches.
Scope: Constants can be declared within various scopes, including the global scope, allowing for program-wide access if necessary. However, it's generally recommended to keep constants within the appropriate scope for better organization and encapsulation.
Constant Expressions: The value assigned to a constant must be a constant expression. This means the expression can be evaluated entirely at compile time, ensuring the value is known before the program runs.
Naming Convention: Rust adheres to the screaming snake case convention for constants. This means all letters are uppercase, and underscores separate words (e.g.,
MAX_VALUE
).
Static Variables
💡 In Rust, global variables are called static
variables. Static variables are declared using the static
keyword, and its naming convention and type annotation are the same as the constants. Static variables could be declared in any scope including the global scope.
💡 Static variables can only store references with the 'static
lifetime, which means the Rust compiler can figure out the lifetime and we aren’t required to annotate it explicitly. Accessing an immutable static variable is safe.
Key Characteristics of Constants:
Immutability: Unlike the constants, static variables can be marked as mutable using
mut
keyword. However, accessing or modifying a mutable static variable is unsafe, therefore, those operations must be done within an unsafe block.Memory management: When using constant variables, the value of the constant will be inline. The constants do not occupy a specific location in memory. Constants are allowed to duplicate their data whenever they’re used.
On the other hand, static variables do occupy a specific location in memory, which means there’s only one instance of the value. It means, a static variable has a fixed address in memory, therefore, using that value will always access the same data.
In general, it's best practice to use constants whenever possible. Static variables should be reserved for specific scenarios. These scenarios include:
Storing large amounts of data: Constants are limited in size by the type they represent. If you need to store a significant amount of data that cannot be easily divided into smaller pieces, a static variable might be necessary.
Needing a single, fixed memory location: Static variables have a unique memory address throughout the program's execution. This property can be useful in limited situations.
Using interior mutability: In rare cases, you might need a data structure that allows modification of specific parts while maintaining immutability for the overall structure. This advanced technique, known as interior mutability, often relies on static variables.
Functions
💡 Functions are defined using the fn
keyword followed by the name of the function and then parentheses, which hold parameters.
Rust code uses snake case as the conventional style for function and variable names, in which all letters are lowercase and underscores separate words.
Rust functions use an arrow (
>
) followed by the type of value the function will return (e.g.,> u32
) to represent the return type of the function. If no return type is specified, the function returns the unit type (()
), which essentially means it doesn't return a value.
Control Flows in Rust
💡 Control flow statements in Rust dictate the order in which your program executes code blocks. They allow you to conditionally execute code based on certain criteria or repeat code a specific number of times.
if Expressions
Used for simple conditional execution.
Checks a boolean expression.
If the expression is
true
, the code block following theif
keyword is executed.
if-else Statements
Similar to if
expressions but provide an alternative code block to run if the condition is false
.
else if
Allows for chaining multiple conditional checks within an if
statement.
if let
💡 In Rust, if let
is a concise way to combine conditional checks with pattern matching, specifically for handling values that match a single pattern. It offers a more readable and less verbose alternative to traditional if
statements, especially when dealing with Option types or enums.
Structure:
<pattern>
: This defines the pattern you want to match against the value from the<expression>
. It can be a variable name, a literal value, or a more complex structure like a tuple or struct.<expression>
: This is the value you want to check against the pattern.
Functionality:
If the pattern in
<pattern>
matches the value from<expression>
, the code block within the curly braces is executed.Any variables defined within the pattern are bound to the corresponding values from the expression, making them accessible within the code block.
If the pattern doesn't match, the
if let
block is skipped, and execution continues after it.
Loops
💡 Used to repeat a block of code multiple times.
💡 while Loop: Executes a code block as long as a condition remains true.
💡 loop: An infinite loop that continues until explicitly broken.
break and continue:
break
: Exits a loop prematurely.continue
: Skips the current iteration of a loop and moves to the next.
💡 for Loop: Iterates over a collection or range of values.
Match Expressions
💡 Provide a cleaner way to handle different variants of a value compared to long if-else
chains.
Last updated