- Struktur elan etmək, onun nümunəsini yaratmaq və
#[derive(Debug)]ilə çap etmək implblokunda&self,&mut selfmetodları və əlaqəli funksiyalar yazmaq- Məlumat daşıyan variantları olan
enumyaratmaq və onu tammatchilə emal etmək - Olmaya bilən qiyməti
Option,if letvəunwrap_orilə təhlükəsiz idarə etmək
Elektron jurnalda hər şagirdin adı, sinfi və orta balı var — bu üç qiyməti ayrı-ayrı dəyişənlərdə saxlamaq əlverişsizdir, onları bir yerdə saxlamaq lazımdır. Svetofor isə eyni anda yalnız bir vəziyyətdə olur: qırmızı, sarı və ya yaşıl. Rust-da birinci hal üçün strukturlar (struct), ikinci hal üçün sadalamalar (enum) var.
Strukturlar
Struktur adlı sahələri olan tipdir. Tipin adı PascalCase ilə, sahələr isə snake_case ilə yazılır. Nümunə yaradanda bütün sahələrə qiymət verilməlidir, sahəyə isə nöqtə ilə müraciət olunur: aysel.score. Sahəni dəyişmək üçün bütün nümunə mut olmalıdır — Rust-da ayrıca sahəni mut etmək olmur.
#[derive(Debug)]
struct Student {
name: String,
grade: u8,
score: f64,
}
fn main() {
let mut aysel = Student {
name: String::from("Aysel"),
grade: 9,
score: 91.5,
};
aysel.score += 2.0;
println!("{} is in grade {}", aysel.name, aysel.grade);
println!("{:?}", aysel);
println!("{:#?}", aysel);
}Aysel is in grade 9
Student { name: "Aysel", grade: 9, score: 93.5 }
Student {
name: "Aysel",
grade: 9,
score: 93.5,
}#[derive(Debug)] atributu kompilyatora strukturu {:?} ilə çap etməyi öyrədir. {:#?} isə hər sahəni ayrıca sətirdə, səliqəli göstərir.Metodlar və impl
Tipə aid funksiyalar impl blokunda yazılır. Birinci parametri self olan funksiya metoddur və nöqtə ilə çağırılır: room.area(). self parametri olmayan funksiya isə əlaqəli funksiyadır, :: ilə çağırılır: Rectangle::new(4, 3) — String::from da məhz belədir. impl daxilində Self yazılışı tipin öz adını əvəz edir.
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn new(width: u32, height: u32) -> Self {
Self { width, height }
}
fn area(&self) -> u32 {
self.width * self.height
}
fn scale(&mut self, factor: u32) {
self.width *= factor;
self.height *= factor;
}
}
fn main() {
let mut room = Rectangle::new(4, 3);
println!("Area: {}", room.area());
room.scale(2);
println!("Scaled: {}x{}, area {}", room.width, room.height, room.area());
}Area: 12 Scaled: 8x6, area 48
| Birinci parametr | Mənası | Çağırış |
|---|---|---|
&self | nümunəni yalnız oxuyur | room.area() |
&mut self | nümunəni dəyişir | room.scale(2) |
self | sahibliyi götürür, nümunə sonra istifadə olunmur | text.into_bytes() |
self yoxdur | əlaqəli funksiya, çox vaxt konstruktor | Rectangle::new(4, 3) |
Enum və match
enum qiymətin bir neçə variantdan biri olduğunu bildirir. Rust-da variantlar öz məlumatlarını da daşıya bilər: heç nə, adlı sahələr və ya mötərizədə qiymətlər. Enum-u match ilə emal edirlər: hər qol nümunə => ifadə şəklindədir. match tam olmalıdır — hər mümkün variant nəzərə alınmalıdır, əks halda kod kompilyasiya olunmur.
enum Command {
Quit,
Move { x: i32, y: i32 },
Say(String),
}
fn run(cmd: &Command) -> String {
match cmd {
Command::Quit => String::from("bye"),
Command::Move { x, y } => format!("move to ({x}, {y})"),
Command::Say(text) => format!("say: {text}"),
}
}
fn main() {
let commands = [
Command::Say(String::from("hello")),
Command::Move { x: 3, y: -1 },
Command::Quit,
];
for cmd in &commands {
println!("{}", run(cmd));
}
}say: hello move to (3, -1) bye
format! println! kimi işləyir, amma mətni ekrana çıxarmır, String kimi qaytarır. match qolunda x, y və text variantın içindəki məlumatla bağlanır.fn day_type(day: u8) -> char {
match day {
1..=5 => 'W',
6 | 7 => 'H',
}
}fn day_type(day: u8) -> char {
match day {
1..=5 => 'W',
6 | 7 => 'H',
_ => '?',
}
}u8 0-dan 255-ə qədər ola bilər, ona görə kompilyator yazır: non-exhaustive patterns: 0_u8 and 8_u8..=u8::MAX not covered. _ «qalan hər şey» deməkdir. Nümunələrdə diapazon (1..=5) və «və ya» (6 | 7) da işlətmək olar.null əvəzinə Option
Rust-da null yoxdur. Qiymət ola da, olmaya da bilərsə, standart kitabxanadakı Option<T> enum-u işlədilir: Some(qiymət) və ya None. Onun içindəki qiymətdən birbaşa istifadə etmək olmaz — kompilyator səni None halını da nəzərə almağa məcbur edir. Yalnız bir variant maraqlıdırsa, uzun match əvəzinə qısa if let yazmaq olar.
fn find_index(names: &[&str], target: &str) -> Option<usize> {
for (i, name) in names.iter().enumerate() {
if *name == target {
return Some(i);
}
}
None
}
fn main() {
let names = ["Elvin", "Leyla", "Murad"];
match find_index(&names, "Leyla") {
Some(i) => println!("Leyla is at {i}"),
None => println!("Leyla not found"),
}
if let Some(i) = find_index(&names, "Nigar") {
println!("Nigar is at {i}");
} else {
println!("Nigar not found");
}
let murad = find_index(&names, "Murad");
println!("{:?} {}", murad, murad.unwrap_or(0));
}Leyla is at 1 Nigar not found Some(2) 2
unwrap_or(0) Some içindəki qiyməti, None olduqda isə verilən ehtiyat qiyməti qaytarır. Standart kitabxanada eyni işi görən hazır metod da var: names.iter().position(|n| *n == target).Əsas fikirlər
structadlı sahələri bir tipdə birləşdirir;#[derive(Debug)]onu{:?}ilə çap etməyə imkan verir.- Metodlar
implblokunda yazılır:&selfoxuyur,&mut selfdəyişir;self-siz funksiyaTip::ad()ilə çağırılır. enumvariantları məlumat daşıya bilər;matchbütün variantları əhatə etməlidir,_qalanları tutur.- Rust-da
nullyoxdur: olmaya bilən qiymətOption<T>—Some(x)və yaNone— ilə ifadə olunur. unwrap()None-da panikaya düşür;match,if letvəunwrap_ordaha təhlükəsizdir.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.