آموزش Rust-قسمت چهارم(نوع داده ها)

راست یک زبان نوع ایستاست(Statically type language).مفهومش اینه که کامپایلر در زمان اجرای برنامه باید از نوع تمامی متغیرهای استفاده شده در برنامه خبر داشته باشه.بعضی موارد پیش میاد که خود کامپایلر می تونه حدس بزنه که چه نوعی رو برای متغیربر اساس مقداری که بهش دادیم، انتخاب کنه و بعضی مواقع نمی تونه یه مثال:

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

مثال بالا یک رشته عددی رو با کمک متد ()parse به عدد تبدیل می‌کنه و اون رو در متغیر از نوع اعداد غیرعلامت دار میریزه (جلوتر بیشتر توضیح میدیم).متد ()expect برای جلوگیری از خطاست به این معنا که اگر کاربری به جای عدد مثلا رشته "42w" رو وارد کرد و ()parse نتونست این رشته رو به عدد تبدیل کنه متد ()expect رشته ی "Not a number" رو به عنوان پیغام خطا چاپ می‌کنه.

اگر در مثال بالا نوع داده رو مشخص نکینم با خطای زیر رو به رو می‌شیم:

error[E0282]: type annotations needed  
--> src/main.rs:2:9   
    | 
2  |     let guess = "42".parse().expect("Not a number!");   
    |          ^^^^^   
    |        
    |   |         cannot infer type for `_`   
    |         consider giving `guess` a type

نوع‌های مقیاسی

نوع مقیاسی نمایش دهنده ی یه مقدار هست.راست از چهار نوع مقیاس متفاوت پشتیبانی می‌کنه.اعداد صحیح(Integer)،اعداد اعشار(floating-point numbers)،بولی(Boolean)،کارکتر(char).

اعداد صحیح

بازه‌ی اعداد صحیح علامت‌دار از فرمول زیر استفاده میشه:

بازه‌اعداد غیرعلامت دار هم :


جدول زیر انواع داده صحیح علامت دار و غیر علامت دار رو همراه با مقدار حافظه‌ای که در بر می‌گیرند نمایش میده.

به عنوان مثال اگر بخوایم بازه‌ی اعدادی که در نوع i8 در نظر بگیریم از فرمول بالا استفاده می‌کنیم که میشه 127 تا 128- میشه.نوع مقادیری که میشه به انواع جدول بالا داد در جدول زیر هست:

حالا از کجا تشخیص بدیم که برای برنامه مون چه نوعی رو انتخاب کنیم؟به صورت پیش فرض i32 توسط کامپایلر انتخاب میشه که بهترین انتخاب هست حتی توی سیستم های 64بیتی.

سرریز اعداد صحیح(Integer Overflow)

فرض کنید از u8 برای برنامه مون استفاده کنیم بازی u8 از 0 تا 255 هست خب اگر من برنامه نویس به اشتباه عدد 256 رو وارد کنم چی اتفاقی میفته؟اگر توی حالت Debug Mode باشه کامپایلر در هنگام اجرا اخطار میده (Panic).اگر در حالت Release Mode باشه Rust پیغام خطای نمایش نمیده و به جاش عدد 256 رو به مکمل دو تبدیل میکنه که میشه 0 و اگر 257 بزنیم مکمل دو میشه 1.

اعداد اعشاری

دو نوع f32 و f64 هست که به صورت پیش فرض اگر در عدد اعشار وارد شده نوع رو مشخص نکینم Rust f64 رو انتخاب می‌کنه که خود راست دلیل این کار رو به دلیل سرعت بالا در cpu های مدرن می‌دونه مثال:

fn main() {     
    let x = 2.0; // f64 
    let y: f32 = 3.0; // f32
}

عملگرهای عددی

شامل جمع،تفریق،ضرب و تقسیم هست:

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;      
    // remainder 
    let remainder = 43 % 5; 
 }

نوع بولی

مثل زبان های برنامه نویسی دیگه دارای دو مقدار false و true داره.

fn main() {     
    let t = true;      
    let f: bool = false; // with explicit type annotation
}

نوع کاراکتری

حروف در Rust با استفاده از ' Single Qution جدا میشن.

fn main() {     
    let c = 'z';     
    let z = 'ℤ';     
    let heart_eyed_cat = '😻';
}

انواع مرکب تاپل

تاپل ها یکی از راه های گروه بندی کردن انواع مختلف هست.تاپل ها دارای طول یکسان هستند به این معنا که زمانی که یک تاپل رو ساختید دیگه نمی‌تونید طولش رو افزایش یا کاهش بدین.برای ساخت تاپل باید از اعداد رو با کاما در داخل پرانتز از هم جدا کنید و هر عدد می‌تونه نوع متفاوتی داشته باشه

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

برای خواندن مقادیر از تاپل از دو روش میشه استفاده کرد که با مثال نمایش دادم:

fn main() {     
    let tup = (500, 6.4, 1);      
    let (x, y, z) = tup;      
    println!("The value of y is: {}", y); 
}

در مثال بالا یه تاپل بدون در نظر گرفتن نوع‌ها ایجاد کردیم و حالا هر مقدار رو به در خط دوم به یک متغیر نسبت دادیم و وقتی y رو چاپ کنیم مقدار 6.4 چاپ میشه.

روش دوم: فراخوانی مستقیم مقدارها با استفاده از .

let x: (i32, f64, u8) = (500, 6.4, 1);      
let five_hundred = x.0;      
let six_point_four = x.1;      
let one = x.2;

اگر با زبان‌های برنامه نویسی دیگه آشنا باشید معمولا اون ها هم مثل Rust اندیس‌هاشون از 0 شروع میشه.

نوع مرکب آرایه

راه دیگه برای گروه‌بندی کردن مقادیر استفاده از آرایه هاست،فرقش با تاپل اینه که مثل تاپل نمی‌تونید انواع مختلفی رو در یه آرایه کنار هم قرار بدین به معنای دیگه اگر در یک آرایه عدد عنصر اول عدد بود باید تا آخرین عنصر عدد باشه یا اگر یک عنصر رشته بود باید عناصر دیگه هم رشته باشه و به جای پرانتز از براکت استفاده می کنه.

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

به گفته خود سایت Rust، آرایه ها زمانی خیلی مفید هستند که می‌خوایم تقسیم حافظه در Stack به جای Heap باشه که در این مورد توی آموزش های بعدی صحبت می‌کنیم.یه مثال دیگه برای رشته‌ها.

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

برای آرایه ها می‌تونیم تعداد و نوع مشخص کنیم.

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

اگر می خواید یه آرایه درست کنید که دارای پنج آرایه باشه و هر پنج آرایه دارای مقدار 3 باشن

let a = [3, 3, 3, 3, 3];

راه دوم

let a = [3; 5];

خواندن اعداد از آرایه‌ها

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

اگر اندیس آرایه‌ای رو اشتباه وارد کنید با خطا مواجه میشین

fn main() {     
    let a = [1, 2, 3, 4, 5];     
    let index = 10;      
    let element = a[index];      
    println!("The value of element is: {}", element); 
}

آرایه ی مثال بالا دارای پنج عنصر هست اما ما عنصر 10 رو درخواست کردیم و برنامه در هنگام اجرا خطای زیر رو نمایش میده:

$ cargo run    
    Compiling arrays v0.1.0 (file:///projects/arrays)     
    Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs      
    Running `target/debug/arrays` thread 'main' panicked at 'index out of bounds: the len is 5 but the index is  10', src/main.rs:5:19 note: Run with `RUST_BACKTRACE=1` for a backtrace.

خب این آموزش هم تموم شد توی آموزش بعدی درباره‌ی فانکشن ها صحبت می‌کنیم.

https://virgool.io/@komeilshahmoradi/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-rust-%D9%82%D8%B3%D9%85%D8%AA-%D9%BE%D9%86%D8%AC%D9%85%D8%AA%D9%88%D8%A7%D8%A8%D8%B9-yfbfbeugvbwt