পাঠ ৩.১

Variable এবং Mutability

Variables and Mutability

Rust-এ variable default-এ immutable — মান একবার দিলে আর বদলানো যায় না। এটা language-এর অন্যতম পরিচায়ক feature, যেটা safety এবং easy concurrency-র দিকে তোমাকে ঠেলে দেয়। দরকার হলে অবশ্যই mutable বানানো যায়।

Default-এ immutable

একটা নতুন project বানিয়ে test করি:

terminalbash
$ cargo new variables

src/main.rs-এ এই code লেখো — এটা compile হবে না:

src/main.rsrust
fn main() {
    let x = 5;
    println!("The value of x is: {x}");
    x = 6;
    println!("The value of x is: {x}");
}

cargo run চালালে error:

compile errortext
error[E0384]: cannot assign twice to immutable variable `x`
 --> src/main.rs:4:5
  |
2 |     let x = 5;
  |         - first assignment to `x`
3 |     println!("The value of x is: {x}");
4 |     x = 6;
  |     ^^^^^ cannot assign twice to immutable variable
  |
help: consider making this binding mutable
  |
2 |     let mut x = 5;
  |         +++

Compiler বলছে — immutable variable-এ দ্বিতীয়বার assign করা যাবে না। এই compile-time error গুরুত্বপূর্ণ: যখন তুমি বলেছ একটা value বদলাবে না, Rust নিশ্চিত করে যে আসলেই বদলায়নি। ফলে code পড়া সহজ — কোথাও surprise বদল নেই।

Mutable variable

mutable করতে variable-এর নামের আগে mut keyword যোগ করো। mut পরবর্তী reader-কে জানিয়েও দেয় — "এই variable-এর value পরে বদলাবে"।

src/main.rsrust
fn main() {
    let mut x = 5;
    println!("The value of x is: {x}");
    x = 6;
    println!("The value of x is: {x}");
}
terminalbash
$ cargo run
The value of x is: 5
The value of x is: 6

mut use করব কিনা — এটা পুরোটাই তোমার choice। কিছু জায়গায় mutability code-কে স্পষ্ট করে, কিছু জায়গায় immutability।

Constants

Constant-ও immutable variable-এর মতো — কিন্তু কয়েকটা পার্থক্য আছে:

  • mut use করা যায় না — constant সবসময় immutable।
  • let-এর জায়গায় const keyword।
  • Type annotate করা আবশ্যক
  • যেকোনো scope-এ declare করা যায়, এমনকি global-এও।
  • শুধু constant expression set করা যায় — runtime-এ compute হওয়া কিছু না।
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;

Constant-এর নামের convention — সব uppercase, word-এর মাঝে underscore। Rust compile-time-এ কিছু simple operation evaluate করতে পারে, তাই 10_800 না লিখে 60 * 60 * 3 লেখা যায় — পরের developer-এর জন্য অর্থ স্পষ্ট থাকে।

Constants সারা program-এ valid থাকে এবং একই hardcoded value একাধিক জায়গায় ব্যবহার হলে সেগুলোকে constant হিসেবে নাম দেওয়া maintainability-র জন্য ভালো।

Shadowing

Rust-এ একই নামে নতুন variable declare করা যায় — পুরোনোটাকে নতুনটা shadow করে। এর মানে compiler পরবর্তী জায়গায় সেই নাম দেখলে নতুন variable-টাই দেখবে।

src/main.rsrust
fn main() {
    let x = 5;

    let x = x + 1;

    {
        let x = x * 2;
        println!("The value of x in the inner scope is: {x}");
    }

    println!("The value of x is: {x}");
}
terminal outputtext
The value of x in the inner scope is: 12
The value of x is: 6

এখানে — প্রথমে x = 5, তারপর let x = x + 1 পুরোনো x (5) ব্যবহার করে নতুন x (6) তৈরি করে। inner block-এ আবার let x = x * 2 নতুন একটা x (12) বানায় — কিন্তু সেটা শুধু সেই block-এর ভিতরে valid। Block শেষ হলে outer-এর x-এ ফিরে আসা হয়, যার value 6।

Shadowing বনাম mut — পার্থক্য

প্রথম পার্থক্য — shadowing-এর জন্য let keyword আবার লিখতে হয়। ভুলে গেলে compile error — যেটা একটা গুরুত্বপূর্ণ safeguard। Transformation-এর পর variable-টা আবার immutable হয়ে যায়।

দ্বিতীয় পার্থক্য — shadowing আসলে নতুন variable তৈরি করে, তাই type-ও বদলানো যায়। Mutable variable-এ type বদলানো যায় না।

fn main() {
    let spaces = "   ";
    let spaces = spaces.len();
}

এখানে প্রথম spaces string, দ্বিতীয়টা number। Shadowing-এ type-conversion-এর জন্য আলাদা নাম (spaces_str, spaces_num) লাগে না।

কিন্তু mut দিয়ে এটা করতে চাইলে error:

fn main() {
    let mut spaces = "   ";
    spaces = spaces.len();
}
compile errortext
error[E0308]: mismatched types
 --> src/main.rs:3:14
  |
2 |     let mut spaces = "   ";
  |                      ----- expected due to this value
3 |     spaces = spaces.len();
  |              ^^^^^^^^^^^^ expected `&str`, found `usize`

এই পাঠ থেকে যা শিখলে

  • let-এ variable default-এ immutable; let mut দিয়ে mutable।
  • const সবসময় immutable, type annotation আবশ্যক, শুধু constant expression।
  • Shadowing — একই নামে নতুন let; type বদলানো যায়, scope শেষ হলে পুরোনোটায় ফেরা।
  • mut বনাম shadowing — mut একই variable-এর value বদলায়, shadowing নতুন variable বানায়।