Rust: التحكم في تدفق Rust
آخر تحديث: 2026-08-26
matchفي لغة Rust ليستswitch— فهي أقوى لأن المُجمِّع يتحقق للتأكد من أنك قد غطيت جميع الحالات.
يُعد تدفق التحكم العمود الفقري للبرنامج. وبالإضافة إلى if/else التقليدية، تتمتع لغة Rust بميزتين رئيسيتين هما: match مطابقة الأنماط وif let السكر النحوي.
1. ما ستتعلمه
- استخدم
if/else if/elseللتفرع الشرطي - استخدم
matchلمطابقة الأنماط - فحص شامل لـ "match" وأحرف البدل
_ - استخدم
if letلتبسيط عملية مطابقة الوضع الأحادي - إضافة شروط إضافية إلى قاعدة «match guard»
2. قصة حكم لعبة «الحجر والورق والمقص»
(1) التحدي: كتابة منطق اتخاذ القرار في لعبة «الحجر والورق والمقص» باستخدام عبارات if-else
إيما هي مطورة ألعاب ترغب في إضافة ميزة حجر، ورق، مقص إلى لعبتها:
Player's turn: Rock (1), Scissors (2), Paper (3)
Computer: Pick one at random
Needs to be determined: Win, Lose, or Tie
الرمز الذي يستخدم if/else للتحديد:
if Player == 1 && Computer == 1 → Tie
else if Player == 1 && Computer == 2 → Win
else if Player == 1 && Computer == 3 → Lose
... Still needs 6 branches!
عند كتابة عدد كبير من أحرف
if/else، من السهل أن تفوتك بعض التوليفات، كما يصعب قراءتها.
(2) حل أنيق لعبارة match في لغة Rust
fn main() {
let player = 1; // Rock
let computer = 2; // Scissors
let result = match (player, computer) {
(1, 1) | (2, 2) | (3, 3) => "Tie",
(1, 2) | (2, 3) | (3, 1) => "You Win!",
(1, 3) | (2, 1) | (3, 2) => "You Lose!",
_ => "Invalid Punch",
};
println!("Results: {}", result);
}
matchالأمر أشبه بـالحكم هنا: فهو يربط بين مجموعات اللكمات التي يقوم بها اللاعب وتلك التي يقوم بها الكمبيوتر بنسبة واحد إلى واحد، دون أي إغفال أو غموض. ويقوم المُجمِّع بالتحقق مما إذا كنت قد كتبت جميع المجموعات التسع أم لا.
3. التفرع الشرطي باستخدام if/else
(1) الاستخدام الأساسي
fn main() {
let number = 7;
if number < 5 {
println!("A number less than 5");
} else if number == 5 {
println!("The number equals 5");
} else {
println!("The number is greater than 5");
}
}
(2) إذا كان if تعبيرًا — فيمكنه إرجاع قيمة
let condition = true;
let value = if condition { 5 } else { 6 };
// Note:The two branches must be of the same type.
println!("value = {}", value); // value = 5
هام: يجب أن يكون فرعا
ifمن نفس النوع. سيؤدي استخدامif true { 5 } else { "six" }إلى حدوث خطأ في الترجمة.
4. مطابقة الأنماط
(1) قواعد النحو الأساسية
graph TB
A[match Expressions] --> B[Each branch = A Pattern]
B --> C[Pattern match successful → Run this branch]
B --> D[Pattern Mismatch → Try the next branch]
A --> E[Finally, there must be _ Wildcard Fallback]
let number = 3;
match number {
1 => println!("one"),
2 => println!("two"),
3 => println!("three"),
_ => println!("other"), // Wildcard——Match all remaining cases
}
(2) القواعد الأساسية لـ "match"
| القاعدة | الوصف |
|---|---|
| الشمولية | يجب أن تغطي جميع القيم الممكنة؛ وسيؤدي إغفال أي فرع إلى حدوث خطأ في الترجمة |
حرف البدل _ |
يطابق جميع الحالات المتبقية؛ يُوضع في النهاية |
متعدد الأوضاع | |
فرع واحد يتطابق مع أنماط متعددة: 1 | 2 => |
| مطابقة النطاق | 1..=5 يطابق الفاصل المغلق من 1 إلى 5 |
| حارس | شروط إضافية: x if x > 5 => |
(3) مقارنة بين if وmatch
| الخصائص | if/else |
match |
|---|---|---|
| طريقة المطابقة | الشرط المنطقي | مطابقة النمط |
| فحص شامل | لا شيء (يمكن حذف الباقي) | إلزامي (يجب أن يشمل جميع القيم) |
| قدرات التفكيك | لا شيء | يدعم تفكيك قوائم التعداد، والمجموعات، والهياكل |
| المطابقة متعددة القيم | تتطلب التسلسل ` | |
| حالات الاستخدام | فحوصات النطاق، المنطق البولياني | معالجة التعداد، تصنيف القيم، التفكيك |
5. if let — «السكر النحوي»
عندما يكون اهتمامك منصبًّا على نمط معين فقط دون القيم الأخرى، فإن if let تكون أكثر إيجازًا من match:
let optional = Some(5);
// match Writing Style (verbose)
match optional {
Some(value) => println!("The value is: {}", value),
_ => (), // You must write this empty branch.
}
// if let Writing Style (Concise)
if let Some(value) = optional {
println!("The value is: {}", value);
// No need to write _ => ()
}
(4) مرجع سريع لكلمات مفتاحية تدفق التحكم
| الكلمة الرئيسية/الصيغة | الغرض | مثال |
|---|---|---|
if / else if / else |
التفرع الشرطي | if x > 0 { ... } else { ... } |
match |
مطابقة الأنماط | match x { 1 => ..., _ => ... } |
if let |
سكر نحوي مطابق أحادي الوضع | if let Some(v) = x { ... } |
while |
الحلقات الشرطية | while x > 0 { ... } |
while let |
حلقة مطابقة الأنماط | while let Some(v) = iter.next() { ... } |
loop |
حلقة لا نهائية | loop { ... break; } |
| التنقل عبر المكرر | ||
break |
الخروج من الحلقة | break; أو break value; |
continue |
تخطي هذه الدورة | continue; |
6. مثال كامل
(1) ▶ المثال:تصنيف الدرجات باستخدام if/else (مستوى الصعوبة ⭐)
// ============================================
// Use if expression to grade scores and return a string
// ============================================
fn main() {
let score = 88;
let grade = if score >= 90 {
"Excellent (A)"
} else if score >= 80 {
"Good (B)"
} else if score >= 70 {
"Intermediate (C)"
} else if score >= 60 {
"Passing Grade (D)"
} else {
"Fail (F)"
};
println!("Fractions: {}, Level: {}", score, grade);
}
الناتج:
Fractions: 88, Level: Good (B)
ifيجب أن تُرجع كل فرع من فروع التعبير نفس النوع. وهنا، تُرجع جميع الفروع&str، لذا فإن المُترجم راضٍ عن ذلك.
(2) ▶ المثال:استخدام match للتعامل مع رموز حالة HTTP (مستوى الصعوبة: ⭐⭐)
// ============================================
// Use match to gracefully handle HTTP Status Codes
// ============================================
fn handle_status_code(code: u16) -> &'static str {
match code {
200 => "OK: Request Successful",
201 => "Created: The resource has been created",
204 => "No Content: No results found",
301 | 302 => "Redirect: The resource has been moved",
400 => "Bad Request: Invalid request format",
401 => "Unauthorized: Unauthorized",
403 => "Forbidden: Access Denied",
404 => "Not Found: Resource does not exist",
500 => "Internal Server Error: Internal Server Error",
502 | 503 => "Server Error: The server is temporarily unavailable",
_ => "Unknown: Unknown status code",
}
}
fn main() {
let codes = [200, 404, 418, 500];
for &code in codes.iter() {
println!("Status Code {}: {}", code, handle_status_code(code));
}
}
الناتج:
Status Code 200: OK: Request Successful
Status Code 404: Not Found: Resource does not exist
Status Code 418: Unknown: Unknown status code
Status Code 500: Internal Server Error: Internal Server Error
|يتيح هذا المشغل للمفرع مطابقة أنماط متعددة، مما يمنع تكرار الكود._تضمن أحرف البدل تغطية جميع رموز الحالة.
(3) ▶ المثال:حراس المطابقة و if let (الصعوبة ⭐⭐)
// ============================================
// match Guard + if let Simplified Pattern Matching
// ============================================
fn main() {
let number = Some(42);
// match Guard: Add additional conditions to the pattern
match number {
Some(x) if x > 100 => println!("Very Large Numbers: {}", x),
Some(x) if x > 50 => println!("Big Numbers: {}", x),
Some(x) => println!("Small numbers: {}", x),
None => println!("No numbers"),
}
// if let Syntactic sugar -- Only care about the Some case
let value = Some("Rust");
if let Some(lang) = value {
println!("Language is: {}", lang);
}
// if let with else
let empty: Option<i32> = None;
if let Some(x) = empty {
println!("Not null: {}", x);
} else {
println!("No value");
}
}
الناتج:
Small numbers: 42
Language is: Rust
No value
استخدم الكلمة الرئيسية
ifفي عبارة المطابقة لإضافة شرط إضافي بعد النمط — ولن يتم الدخول إلى هذا الفرع إلا إذا تطابق النمط وكان الشرط صحيحًا. وتُعدif letمناسبة للحالات التي «لا تهتم فيها إلا بنمط واحد».
(4) ▶ المثال:استخدام match لتفكيك القوائم التعدادية والمجموعات (مستوى الصعوبة: ⭐⭐⭐)
// ============================================
// match Deconstruction: Enumeration + Tuple + Guard
// ============================================
enum Shape {
Circle(f64),
Rectangle(f64, f64),
Triangle(f64, f64, f64),
}
fn describe_shape(shape: &Shape) -> String {
match shape {
Shape::Circle(radius) if *radius > 10.0 => {
format!("Big Circle (Radius {:.1})", radius)
}
Shape::Circle(radius) => {
format!("Small Circle (Radius {:.1})", radius)
}
Shape::Rectangle(w, h) if w == h => {
format!("Square (Side length {:.1})", w)
}
Shape::Rectangle(w, h) => {
format!("Rectangle (Width {:.1}, Height {:.1})", w, h)
}
Shape::Triangle(a, b, c) => {
format!("Triangle (Sides {:.1}, {:.1}, {:.1})", a, b, c)
}
}
}
fn main() {
let shapes = [
Shape::Circle(5.0),
Shape::Circle(15.0),
Shape::Rectangle(4.0, 4.0),
Shape::Rectangle(3.0, 5.0),
Shape::Triangle(3.0, 4.0, 5.0),
];
println!("=== Graphical Description ===");
for shape in &shapes {
println!("{}", describe_shape(shape));
}
println!("\n=== Coordinate Classification ===");
let points: [(i32, i32); 4] = [(0, 0), (3, 0), (0, -2), (5, 7)];
for point in points {
let desc = match point {
(0, 0) => "Origin".to_string(),
(x, 0) => format!("On x-axis (x={})", x),
(0, y) => format!("On y-axis (y={})", y),
(x, y) if x > 0 && y > 0 => format!("First Quadrant ({}, {})", x, y),
(x, y) => format!("Other Quadrants ({}, {})", x, y),
};
println!("Point {:?}: {}", point, desc);
}
}
الناتج:
=== Graphical Description ===
Small Circle (Radius 5.0)
Big Circle (Radius 15.0)
Square (Side length 4.0)
Rectangle (Width 3.0, Height 5.0)
Triangle (Sides 3.0, 4.0, 5.0)
=== Coordinate Classification ===
Point (0, 0): Origin
Point (3, 0): On x-axis (x=3)
Point (0, -2): On y-axis (y=-2)
Point (5, 7): First Quadrant (5, 7)
تتيح لك إمكانيات تفكيك البنية في
matchإمكانية مطابقة متغيرات التعداد واستخراج القيم الداخلية وتطبيق شروط الحراسة في آن واحد، من أجل تنفيذ منطق تصنيف دقيق. ويضمن الفحص الشامل الذي يقوم به المُجمِّع ألا تغفل أي حالة.
(5) ▶ المثال:التطبيق العملي لـ if let و while let (مستوى الصعوبة: ⭐⭐)
// ============================================
// if let and while let: Simplify Option/Result Processing
// ============================================
fn divide(a: f64, b: f64) -> Option<f64> {
if b == 0.0 {
None
} else {
Some(a / b)
}
}
fn main() {
println!("=== if let Processing Option ===");
let results = [divide(10.0, 2.0), divide(8.0, 0.0), divide(15.0, 3.0)];
for result in &results {
if let Some(value) = result {
println!("Division Successful: {:.2}", value);
} else {
println!("Division Failed: Divisor is zero");
}
}
println!("\n=== if let Chain Processing ===");
let alice_input: Option<&str> = Some("42");
let bob_input: Option<&str> = None;
if let Some(num_str) = alice_input {
if let Ok(num) = num_str.parse::<i32>() {
println!("Alice's number: {}", num);
}
}
if let Some(num_str) = bob_input {
if let Ok(num) = num_str.parse::<i32>() {
println!("Bob's number: {}", num);
}
} else {
println!("Bob has no data input");
}
println!("\n=== while let Simulation Iteration ===");
let mut stack = vec![3, 2, 1];
while let Some(top) = stack.pop() {
println!("Popped: {}", top);
}
println!("The stack is empty");
}
الناتج:
=== if let Processing Option ===
Division Successful: 5.00
Division Failed: Divisor is zero
Division Successful: 5.00
=== if let Chain Processing ===
Alice's number: 42
Bob has no data input
=== while let Simulation Iteration ===
Popped: 1
Popped: 2
Popped: 3
The stack is empty
if letمناسب للحالات التي لا يهمك فيها سوىSome/Okويمكنك تجاهل الحالات الأخرى؛ أماwhile letفهو مناسب للحالات التي تقوم فيها بالتكرار عبر القيم حتى تصادفNone(مثل عمليات المكدسpop()). وكلاهما أكثر إيجازًا منmatchالكامل.
❓ أسئلة شائعة
match وswitch؟match أقوى بكثير من switch.match مهمًا جدًّا؟if let؟match؟if من نوعين مختلفين؟📖 ملخص
if/elseهو تعبير (يمكن أن يُرجع قيمة)؛ ويجب أن تكون جميع الفروع من نفس النوعmatchعند إجراء مطابقة الأنماط، يفرض المُجمِّع التحقق الشامل- الرمز البديل
_يطابق جميع القيم المتبقية، ويتم وضعه في نهاية عملية المطابقة if letهو تعبير مبسط لـmatch، وهو مناسب للحالات التي «لا تهتم فيها إلا بنمط واحد»- الحارس (مع الشرط
if) يجعل مطابقة الأنماط أكثر مرونة - يسمح عامل
|للفرع بمطابقة أنماط متعددة
📝 تمارين
- الصعوبة ⭐: اكتب دالة
fn number_to_word(n: i32) -> &'static strتستخدمmatchلتحويل الأرقام من 0 إلى 5 إلى الكلمات الإنجليزية المقابلة لها (zero/one/two/three/four/five)، وتُرجع "unknown" لجميع الأرقام الأخرى. - الصعوبة ⭐⭐: قم بتعريف قائمة عدّية
enum TrafficLight { Red, Yellow, Green }واستخدمmatchلإرجاع «وقت الانتظار» المقابل لكل لون (الأحمر: 30 ثانية، الأصفر: 3 ثوانٍ، الأخضر: 45 ثانية). - الصعوبة ⭐⭐⭐ : اكتب دالة
fn describe_point(point: (i32, i32))تستخدمmatchلمعالجة نقطة إحداثيات ثنائية الأبعاد: إذا كانت النقطة تقع عند نقطة الأصل(0,0)، فقم بإخراج "نقطة الأصل"؛ وإذا كانت على المحور x(x,0)، فاطرح "على المحور x"؛ وإذا كانت على المحور y(0,y)، فاطرح "على المحور y"؛ وفي جميع الحالات الأخرى، اطرح قيم الإحداثيات.