לדלג לתוכן

2.10 - יצירת קוד ומאקרואים הניתנים לבדיקה - פתרון

פתרון גבול חזרה בתוך ההרחבה

נשתמש ב־closure פנימית שמחזירה Option. האופרטור ? עוצר את החישוב שלה ולא מחזיר מן הפונקציה שסביבה. הביטויים הבאים אינם מוערכים לאחר גלישה.

macro_rules! sum_values {
    ($($value:expr),* $(,)?) => {{
        (|| -> Option<u64> {
            let mut total = 0u64;
            $(total = total.checked_add($value)?;)*
            Some(total)
        })()
    }};
}

fn main() {
    assert_eq!(sum_values![], Some(0));
    assert_eq!(sum_values![1u64, 2u64], Some(3));
    let mut calls = 0;
    let result = sum_values![
        { calls += 1; u64::MAX },
        { calls += 1; 1u64 },
        { calls += 1; 10u64 },
    ];
    assert_eq!(result, None);
    assert_eq!(calls, 2);
}

הרחבה ריקה עשויה להפיק אזהרה על mut שאינו נדרש. אפשר להוסיף זרוע ייעודית למקרה הריק אם רוצים למנוע אותה. התנהגות העצירה אינה תוצר לוואי מקרי: היא חלק מחוזה המאקרו ונבדקת באמצעות המונה.