পাঠ ৩.২

Data Type-সমূহ

Data Types

Rust একটা statically typed language — compile time-এ সব variable-এর type জানা থাকতে হবে। সাধারণত compiler value দেখে infer করতে পারে, কিন্তু একাধিক type সম্ভব হলে আমাদের explicit annotation দিতে হয়:

let guess: u32 = "42".parse().expect("Not a number!");

: u32 না দিলে compile error — কারণ parse অনেক type-এ convert করতে পারে।

এই পাঠে দুটো বড় category দেখব — scalar (একটামাত্র value) এবং compound (একাধিক value একসাথে)।

Scalar type

Rust-এ চারটে primary scalar type — integer, floating-point, Boolean, এবং character।

Integer

সংখ্যা — যাদের decimal নেই। i দিয়ে শুরু হলে signed (negative হতে পারে), u দিয়ে শুরু হলে unsigned (শুধু non-negative)। size bits-এ:

Table 3-1text
Length     | Signed | Unsigned
8-bit      | i8     | u8
16-bit     | i16    | u16
32-bit     | i32    | u32
64-bit     | i64    | u64
128-bit    | i128   | u128
arch-dep   | isize  | usize

Signed range: −2^(n−1) থেকে 2^(n−1)−1। যেমন i8: −128 থেকে 127। Unsigned range: 0 থেকে 2^n−1। যেমন u8: 0 থেকে 255।

isizeusize তোমার machine-এর architecture-এর উপর নির্ভর করে — 64-bit machine-এ 64 bits, 32-bit machine-এ 32 bits। সাধারণত collection index করার সময় use করা হয়।

Rust-এ integer literal কয়েকভাবে লেখা যায়:

Table 3-2text
Number literal | Example
Decimal        | 98_222
Hex            | 0xff
Octal          | 0o77
Binary         | 0b1111_0000
Byte (u8)      | b'A'

_ visual separator — 1_000 আর 1000 এক জিনিস। Suffix দিয়েও type fix করা যায় — যেমন 57u8

কোন integer type use করব — confused হলে default-এ i32 দিয়ে শুরু করো; বেশিরভাগ ক্ষেত্রে এটাই সঠিক।

Integer overflow

ধরো u8-এ 256 store করতে চাইলে — range-এর বাইরে। এটাকে বলে integer overflow

  • Debug build-এ — Rust panic করে runtime-এ। "panic" মানে program error দিয়ে exit করা।
  • Release build-এ (--release) — overflow check off। Two's complement wrapping হয় — 256 হয়ে যাবে 0, 257 হবে 1, ইত্যাদি। Program crash হবে না, কিন্তু value তোমার expectation-এর সাথে মিলবে না।

Overflow-কে explicit handle করতে standard library-তে কয়েকটা method family আছে:

  • wrapping_* — সব mode-এ wrap (যেমন wrapping_add)।
  • checked_* — overflow হলে None return।
  • overflowing_* — value এবং একটা boolean (overflow হয়েছে কিনা) return।
  • saturating_* — type-এর min/max-এ আটকে যায়।

Floating-point

Decimal-যুক্ত সংখ্যা। দুটো type — f32 (32 bits) এবং f64 (64 bits)। Default f64 — modern CPU-তে f32-এর প্রায় same speed কিন্তু precision বেশি। দুটোই signed; IEEE-754 standard follow করে।

fn main() {
    let x = 2.0; // f64

    let y: f32 = 3.0; // f32
}

Numeric operations

সব number type-এ basic math — addition, subtraction, multiplication, division, remainder। Integer division zero-এর দিকে truncate করে।

fn main() {
    // addition
    let sum = 5 + 10;

    // subtraction
    let difference = 95.5 - 4.3;

    // multiplication
    let product = 4 * 30;

    // division
    let quotient = 56.7 / 32.2;
    let truncated = -5 / 3; // Results in -1

    // remainder
    let remainder = 43 % 5;
}

Boolean

bool type — দুটো value: true, false। size এক byte।

fn main() {
    let t = true;

    let f: bool = false; // with explicit type annotation
}

সাধারণত if condition-এ ব্যবহার হয়।

Character

char — Rust-এর সবচেয়ে primitive alphabetic type। একটা Unicode scalar value, 4 bytes size।

fn main() {
    let c = 'z';
    let z: char = 'ℤ'; // with explicit type annotation
    let heart_eyed_cat = '😻';
}

char-এর জন্য single quote ('z'); string-এর জন্য double quote ("z")। ASCII-র বাইরে — Bangla, Chinese, Japanese, emoji — সব valid char। তবে সতর্ক: Unicode-এ "character"-এর definition আমাদের intuition-এর মতো নয়, পরে Chapter 8-এ দেখব।

Compound type

একাধিক value একসাথে রাখার জন্য Rust-এ দুটো primitive compound type — tuple এবং array

Tuple

আলাদা আলাদা type-এর value group করার সাধারণ উপায়। fixed length — declare করার পর size বদলানো যায় না।

fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}

Pattern matching দিয়ে individual value বের করা — একে বলে destructuring:

fn main() {
    let tup = (500, 6.4, 1);

    let (x, y, z) = tup;

    println!("The value of y is: {y}");
}

অথবা index দিয়ে সরাসরি access — index 0 থেকে শুরু:

fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let five_hundred = x.0;

    let six_point_four = x.1;

    let one = x.2;
}

Empty tuple — () — একটা special name আছে: unit। যেসব expression কোনো value return করে না, তারা implicitly unit return করে।

Array

Tuple-এর মতো — তবে সব element-এর type একই হতে হবে। size fixed।

fn main() {
    let a = [1, 2, 3, 4, 5];
}

Array data stack-এ allocate হয় (heap-এ না)। Size-পরিবর্তনযোগ্য collection দরকার হলে Vec (vector) use করতে হবে — Chapter 8-এ আসবে।

নির্দিষ্ট সংখ্যক element সবসময় থাকবে — যেমন বছরের ১২ মাস — তখন array ভালো:

let months = ["January", "February", "March", "April", "May", "June", "July",
              "August", "September", "October", "November", "December"];

Array-এর type — [type; size]:

let a: [i32; 5] = [1, 2, 3, 4, 5];

সব element একই value হলে — [value; count]:

let a = [3; 5];

এটা [3, 3, 3, 3, 3]-এর সমান।

Element access

fn main() {
    let a = [1, 2, 3, 4, 5];

    let first = a[0];
    let second = a[1];
}

Invalid index → panic

Array-এর সীমার বাইরে index দিলে runtime error:

use std::io;

fn main() {
    let a = [1, 2, 3, 4, 5];

    println!("Please enter an array index.");

    let mut index = String::new();

    io::stdin()
        .read_line(&mut index)
        .expect("Failed to read line");

    let index: usize = index
        .trim()
        .parse()
        .expect("Index entered was not a number");

    let element = a[index];

    println!("The value of the element at index {index} is: {element}");
}

User 10 দিলে:

terminal outputtext
thread 'main' panicked at src/main.rs:19:19:
index out of bounds: the len is 5 but the index is 10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Rust runtime-এ check করে — index length-এর কম কিনা। কম না হলে panic, program exit। অনেক low-level language এই check করে না — invalid memory access হয়, বড় security risk। Rust এই error থেকে তোমাকে রক্ষা করে।

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

  • Scalar — integer (i8…i128, u8…u128, isize, usize), float (f32, f64), bool, char।
  • Integer overflow — debug-এ panic, release-এ wrap; wrapping_*/checked_*/overflowing_*/saturating_* দিয়ে explicit handle।
  • Compound — tuple (mixed type, fixed length, destructure বা .0); array (একই type, fixed size, stack allocation)।
  • Array-এ out-of-bounds access হলে runtime panic।