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 שאינו נדרש. אפשר להוסיף זרוע ייעודית למקרה הריק אם רוצים למנוע אותה. התנהגות העצירה אינה תוצר לוואי מקרי: היא חלק מחוזה המאקרו ונבדקת באמצעות המונה.