الرئيسية قاعدة المعرفة البرمجة والمنطق التحكم بالتدفق في Rust: الشروط والحلقات في أنظمة المراقبة
البرمجة والمنطق

التحكم بالتدفق في 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 مختصراً وآمناً. في الدرس القادم سنتعلم الدوال — كيف نقسّم البرنامج إلى وحدات قابلة لإعادة الاستخدام.

if-else match loop while for pattern-matching الشروط الحلقات مطابقة الأنماط التدفق المنطقي حلقة المراقبة القرارات