التحكم بالتدفق في Rust: الشروط والحلقات في أنظمة المراقبة
if و else: اتخاذ القرارات
كل نظام مراقبة صناعي يعتمد على قرارات: هل درجة الحرارة تجاوزت الحد؟ هل الضغط طبيعي؟ في Rust، الشروط تُكتب بـ if بدون أقواس حول الشرط (على عكس C):
let temperature = 85.0;
if temperature > 80.0 {
println!("تحذير: درجة حرارة مرتفعة!");
} else if temperature > 60.0 {
println!("طبيعي: درجة الحرارة ضمن النطاق");
} else {
println!("منخفضة: تحقق من المستشعر");
}
ملاحظة مهمة: الشرط يجب أن يكون من نوع bool. لن يقبل Rust if temperature — يجب أن تكتب if temperature > 0.0.
if كتعبير يعيد قيمة
في Rust، if ليس مجرد أمر — بل تعبير يعيد قيمة:
let temperature = 75.0;
let status = if temperature > 80.0 { "خطر" } else { "طبيعي" };
println!("الحالة: {}", status);
هذا يشبه العامل الثلاثي ? : في C، لكن أوضح في القراءة. الشرط: كلا الفرعين يجب أن يعيدا نفس النوع.
match: مطابقة الأنماط القوية
match هي أقوى أداة اتخاذ قرار في Rust. تشبه switch في C لكنها أذكى بكثير — المُجمِّع يُجبرك على تغطية كل الاحتمالات:
enum MachineState {
Running,
Idle,
Error,
Maintenance,
}
let state = MachineState::Running;
match state {
MachineState::Running => println!("الآلة تعمل بشكل طبيعي"),
MachineState::Idle => println!("الآلة في وضع الخمول"),
MachineState::Error => println!("خطأ! تحقق فوراً"),
MachineState::Maintenance => println!("صيانة مجدولة"),
}
إذا حذفت أي حالة — المُجمِّع يرفض الكود. هذا يضمن أنك لن تنسى التعامل مع حالة خطأ في نظام تحكم صناعي.
match مع القيم والنطاقات
let alarm_level: u8 = 3;
let action = match alarm_level {
0 => "لا إنذار",
1 => "تنبيه — راقب الوضع",
2 => "تحذير — تدخل مطلوب قريباً",
3..=5 => "حرج — أوقف الآلة فوراً",
_ => "مستوى غير معروف", // _ يطابق أي قيمة أخرى
};
println!("الإجراء: {}", action);
_ هو نمط الالتقاط العام — يطابق أي قيمة لم تُذكر. النطاق 3..=5 يطابق 3 و 4 و 5.
loop: دورة المراقبة اللانهائية
في الأنظمة الصناعية، كثير من البرامج تعمل إلى ما لا نهاية — تقرأ مستشعرات، تتحقق من الحدود، تسجّل البيانات. loop هي حلقة لانهائية مع إمكانية الخروج بـ break:
let mut cycle_count = 0;
loop {
cycle_count += 1;
let reading = simulate_sensor_read();
if reading > 100.0 {
println!("إنذار في الدورة {}: القراءة {:.1}", cycle_count, reading);
break; // خروج من الحلقة
}
if cycle_count >= 1000 {
println!("اكتمل المسح: {} دورة بدون إنذار", cycle_count);
break;
}
}
loop كتعبير يعيد قيمة
let final_reading = loop {
let r = read_sensor();
if r > 0.0 {
break r; // break مع قيمة يُعيدها loop
}
};
println!("أول قراءة صالحة: {:.1}", final_reading);
while و while let
while تستمر ما دام الشرط صحيحاً:
let mut retries = 0;
while retries < 3 {
match connect_to_plc() {
Ok(_) => {
println!("اتصال ناجح بالمتحكم!");
break;
}
Err(e) => {
retries += 1;
println!("محاولة {} فشلت: {}", retries, e);
}
}
}
while let تجمع بين while وmatch — تستمر ما دام النمط يتطابق:
let mut sensor_queue = vec![23.5, 24.1, 0.0, 25.3];
while let Some(reading) = sensor_queue.pop() {
if reading > 0.0 {
println!("قراءة: {:.1}°C", reading);
}
}
// تتوقف عندما تصبح القائمة فارغة (pop يعيد None)
for والنطاقات: التكرار على بيانات المستشعرات
for هي الحلقة الأكثر استخداماً — تُكرّر على أي مجموعة:
let sensors = [101, 102, 103, 104, 105];
for sensor_id in &sensors {
println!("قراءة المستشعر {}...", sensor_id);
}
النطاقات (Ranges)
// من 0 إلى 9 (لا يشمل 10)
for i in 0..10 {
println!("الدورة {}", i);
}
// من 1 إلى 10 (يشمل 10)
for i in 1..=10 {
println!("القطعة رقم {}", i);
}
enumerate: الفهرس مع القيمة
let readings = [23.5, 24.1, 22.8, 25.0];
for (index, temp) in readings.iter().enumerate() {
println!("المستشعر {}: {:.1}°C", index + 1, temp);
}
التعبيرات وليس الأوامر: if يعيد قيمة
من أهم خصائص Rust أن معظم البنى هي تعبيرات (expressions) وليست أوامر (statements). هذا يعني أنها تعيد قيم:
// if كتعبير
let message = if temperature > 80.0 {
"حرج"
} else {
"طبيعي"
};
// match كتعبير
let priority = match alarm_level {
0 => "منخفض",
1 | 2 => "متوسط",
_ => "عالي",
};
// loop يمكن أن يعيد قيمة عبر break
let result = loop {
let val = compute();
if val > threshold {
break val;
}
};
هذا يقلل الحاجة لمتغيرات mut مؤقتة ويجعل الكود أكثر وضوحاً.
الخلاصة
if/else لقرارات بسيطة، match للمطابقة الشاملة مع ضمان تغطية كل الحالات، loop لدورات المراقبة المستمرة، while للتكرار المشروط، وfor للتكرار على المجموعات. كل هذه البنى تعبيرات تعيد قيماً — مما يجعل كود Rust مختصراً وآمناً. في الدرس القادم سنتعلم الدوال — كيف نقسّم البرنامج إلى وحدات قابلة لإعادة الاستخدام.