Rust Option::is_none_or: เขียนกฎ ‘ไม่มีก็ได้ มีก็ต้องผ่าน’ ให้ตรงความหมาย
configuration หลายช่องเป็น optional: ถ้าไม่ใส่ให้ใช้ default แต่ถ้าใส่มาต้องอยู่ในขอบเขต เดิมเรามักเขียน value.map(predicate).unwrap_or(true) ซึ่งถูกแต่ต้องแปลในหัวสองชั้น Option::is_none_or เขียนกฎนี้ตรงตัวว่า “เป็น None หรือค่าข้างในผ่าน predicate” ครับ
fn valid_timeout(timeout_ms: Option<u64>) -> bool {
timeout_ms.is_none_or(|ms| (100..=30_000).contains(&ms))
}
fn main() {
assert!(valid_timeout(None));
assert!(valid_timeout(Some(5_000)));
assert!(!valid_timeout(Some(50)));
assert!(!valid_timeout(Some(60_000)));
println!("optional timeout validation passed");
}
เมธอดนี้ consume Option<T> ดังนั้นถ้าต้องใช้ค่าต่อและ T ไม่ใช่ Copy ให้เรียกผ่าน as_ref() เช่น name.as_ref().is_none_or(|s| !s.is_empty()) เพื่อประเมิน Option<&T> แทน การเลือก is_none_or ยังช่วย review เพราะคนอ่านเห็นทันทีว่า None เป็นกรณีที่ยอมรับได้
อย่าสลับกับ is_some_and ซึ่งแปลว่า “ต้องมีค่าและค่านั้นผ่าน” ตัวอย่างช่อง timeout ที่ไม่บังคับใช้ is_none_or; แต่ token ที่ต้องมีและห้ามว่างควรใช้ is_some_and หรือคืน error ที่บอกเหตุผลละเอียดกว่า boolean
Recap
- ใช้
is_none_orเมื่อNoneคือค่า valid - ใช้
is_some_andเมื่อการไม่มีค่าต้องตก - ผ่าน
as_ref()หากยังต้องใช้ค่าที่เป็นเจ้าของต่อ - คืน error แทน boolean เมื่อผู้ใช้ต้องรู้เหตุผลที่ไม่ผ่าน