← Rust EnglishChapter 02 of 13

Variables and Mutability

## Learning Objectives - Declare and initialize variables - Understand mutability in Rust - Work with Rust data types - Master type inference - Use type annotations ## Variables ### Declaration ```rust let x = 5; // Immutable variable let mut y = 10; // Mutable variable ``` ### Naming Rules - Start with letter or underscore - Can contain letters, digits, underscores - Case-sensitive - Cannot use reserved words ```rust let age = 25; // Valid let _count = 0; // Valid (suppresses warning) let total_price = 99.99; // Valid // let 2ndPlace = 1; // Invalid: starts with number // let let = 5; // Invalid: reserved word ``` ## Mutability ### Immutable by Default ```rust let x = 5; x = 6; // Error: cannot assign twice to immutable variable ``` ### Making Variables Mutable ```rust let mut x = 5; x = 6; // OK: x is mutable println!("{}", x); // Prints: 6 ``` ### Why Immutability? - Prevents bugs from accidental modification - Enables compiler optimizations - Makes code easier to reason about ## Data Types ### Scalar Types #### Integer Types | Type | Size | Signed | |------|------|--------| | i8 | 8-bit | Yes | | i16 | 16-bit | Yes | | i32 | 32-bit | Yes | | i64 | 64-bit | Yes | | i128 | 128-bit | Yes | | isize | pointer size | Yes | | u8 | 8-bit | No | | u16 | 16-bit | No | | u32 | 32-bit | No | | u64 | 64-bit | No | | u128 | 128-bit | No | | usize | pointer size | No | ```rust let a: i32 = 100; // Decimal let b: i32 = 0x64; // Hexadecimal let c: i32 = 0o144; // Octal let d: i32 = 0b1100100; // Binary let e: i32 = b'C'; // Byte literal let large: i64 = 9_000_000_000; // Underscores for readability ``` #### Floating-Point Types ```rust let f1: f64 = 3.14; // 64-bit, default let f2: f32 = 3.14; // 32-bit println!("{}", std::f64::consts::PI); // Math constant ``` #### Boolean Type ```rust let is_active = true; let is_valid: bool = false; ``` #### Character Type ```rust let c1 = 'a'; // ASCII character let c2 = 'Z'; let c3 = '\u{1F600}'; // Unicode emoji ``` ### Compound Types #### Tuple ```rust let tup: (i32, f64, u8) = (500, 6.4, 1); // or let tup = (500, 6.4, 1); let (x, y, z) = tup; // Destructuring println!("{} {} {}", x, y, z); let first = tup.0; // Access by index let second = tup.1; ``` #### Array ```rust let arr: [i32; 5] = [1, 2, 3, 4, 5]; // or let arr = [1, 2, 3, 4, 5]; let first = arr[0]; // Access by index let len = arr.len(); // Array length // Array with same value let zeros = [0; 5]; // [0, 0, 0, 0, 0] ``` ### Type Inference ```rust let x = 5; // Compiler infers i32 let y = 3.14; // Compiler infers f64 let name = "Alice"; // Compiler infers &str ``` ### Type Annotations ```rust let x: i32 = 5; let y: f64 = 3.14; let name: &str = "Alice"; let arr: [i32; 3] = [1, 2, 3]; ``` ## Constants ### const vs let ```rust let x = 5; // Immutable variable (compiler enforces) const MAX_SIZE: i32 = 100; // Compile-time constant const PI: f64 = 3.14159265359; // Type annotation required const MESSAGE: &str = "Hello"; // String slice ``` ### Differences | Feature | let | const | |---------|-----|-------| | Mutability | With `mut` | Never | | Type annotation | Optional | Required | | Evaluation | Runtime | Compile-time | | Scope | Block | Global | ## Type Conversion ### as Operator ```rust let x: i32 = 5; let y: f64 = x as f64; // i32 to f64 let z: f64 = 3.99; let w: i32 = z as i32; // Truncates to 3 let c: char = 65 as char; // Number to character let n: u8 = b'A'; // Byte literal ``` ### Parse String to Number ```rust let s = "42"; let n: i32 = s.parse().unwrap(); // String to i32 let n: Result = s.parse(); let s = "3.14"; let f: f64 = s.parse().unwrap(); // String to f64 ``` ### Number to String ```rust let n = 42; let s = n.to_string(); // i32 to String let s = format!("{}", n); // Using format macro let f = 3.14; let s = f.to_string(); ``` ## Variables Scope ```rust fn main() { let x = 10; { let y = 20; // Inner scope println!("{} {}", x, y); // OK: both visible } println!("{}", x); // OK: x visible // println!("{}", y); // Error: y not in scope } ``` ## Shadowing ```rust let x = 5; let x = x + 1; // Shadows previous x let x = x * 2; // Shadows again println!("{}", x); // Prints: 12 // Shadowing with different type let spaces = " "; let spaces = spaces.len(); // Now i32 ``` ## Summary - Variables are immutable by default - Use `mut` for mutable variables - Scalar types: integers, floats, booleans, characters - Compound types: tuples, arrays - Type inference reduces verbosity - Constants use `const` keyword (compile-time) - Use `as` for type casting - Shadowing allows re-declaring variables

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →