পাঠ ৫.১

Struct define এবং তৈরি করা

Defining and Instantiating Structs

Struct tuple-এর মতো — একাধিক value এক group-এ রাখে। কিন্তু tuple-এ position দিয়ে access (.0, .1), struct-এ প্রতিটা data-র নাম থাকে — তাই order মনে রাখতে হয় না, code-ও পড়তে সহজ।

Struct define করা

struct keyword + নাম + curly bracket-এ field-এর নাম ও type:

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

Instance তৈরি করা

Struct-এর নাম + curly bracket-এ key: value pair। Field-এর order definition-এর সাথে মিলতে হবে না — নাম দিয়েই identify হচ্ছে:

fn main() {
    let user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };
}

Field access dot notation দিয়ে — user1.email। Modify করতে হলে instance-টা mutable হতে হবে:

fn main() {
    let mut user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };

    user1.email = String::from("anotheremail@example.com");
}

লক্ষ্য করো — Rust-এ শুধু কিছু field-কে mutable mark করা যায় না। পুরো instance mutable, না হলে নয়।

Function থেকে instance return

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username: username,
        email: email,
        sign_in_count: 1,
    }
}

Function-এর শেষ expression হিসেবে instance — implicit return।

Field init shorthand

Parameter আর field-এর নাম একই হলে repeat না করে shorthand লেখা যায়:

fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,
        email,
        sign_in_count: 1,
    }
}

Struct update syntax

এক instance থেকে কয়েকটা field পরিবর্তন করে নতুন instance — .. syntax:

fn main() {
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}

..user1 সবশেষে — বাকি field-গুলো user1 থেকে নিতে বলছে।

Move হয়, copy না

=-এর মতো কাজ করে — যেখানে যেগুলো heap data (String) সেগুলো move হয়। উদাহরণে user1.username user2-এ move হয়েছে; এরপর user1 পুরোটা use করা যাবে না।

কিন্তু যদি email এবং username দুটোই নতুন দিতাম, শুধু activesign_in_count (Copy types) user1 থেকে আসত — তাহলে user1 still valid থাকত।

Tuple struct

নাম থাকে, কিন্তু field-এর নাম থাকে না — শুধু type। Tuple-কে নাম এবং distinct type দিতে চাইলে:

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

black এবং origin আলাদা type — content same হলেও। Color expect-করা function Point accept করবে না।

Destructure আর index access:

let Point(x, y, z) = origin;
let first = origin.0;

Unit-like struct

একদমই কোনো field নেই — শুধু trait implement করার জন্য type চাই, এমন ক্ষেত্রে:

struct AlwaysEqual;

fn main() {
    let subject = AlwaysEqual;
}

Curly bracket বা parenthesis কিছুই লাগে না — শুধু নাম। Trait (Chapter 10)-এ এর use case পরিষ্কার হবে।

কেন String, &str না?

User-এ আমরা String ব্যবহার করেছি, &str না। কারণ — instance নিজেই data-র owner হোক, যাতে struct বেঁচে থাকা পর্যন্ত data-ও থাকে।

Reference রাখতে চাইলে lifetime specify করতে হয়। এমনিতে error:

struct User {
    active: bool,
    username: &str,
    email: &str,
    sign_in_count: u64,
}
compile errortext
error[E0106]: missing lifetime specifier
 --> src/main.rs:3:15
  |
3 |     username: &str,
  |               ^ expected named lifetime parameter

আপাতত String use করো; lifetime Chapter 10-এ বিস্তারিত আসবে।

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

  • struct — named field, position-independent access।
  • Field access dot notation; modify-এর জন্য instance mut হতে হবে — partial mutability নেই।
  • Field init shorthand (variable নাম == field নাম); struct update syntax (..other) — কিন্তু move হয়।
  • Tuple struct — নাম দেওয়া tuple, distinct type। Unit-like struct — শূন্য field, trait-এর জন্য।
  • Struct-এ reference রাখতে গেলে lifetime দরকার; আপাতত owned type (String) ব্যবহার করো।