Rust try_fold: สะสมค่าแล้วหยุดทันทีเมื่อเจอเงื่อนไขผิด
fold เหมาะกับการรวมทุกค่า แต่ถ้าข้อมูลชิ้นหนึ่งทำให้ไปต่อไม่ได้ เราไม่ควรฝืนวิ่งจนจบครับ Iterator::try_fold สะสมค่าเหมือน fold แล้วหยุดทันทีเมื่อ closure คืน Err
WHY: failure เป็นส่วนหนึ่งของการพับข้อมูล
นึกถึงพนักงานบวกราคารายการสินค้า ถ้าเจอราคาติดลบ เขาควรหยุดและส่งใบงานกลับ ไม่ใช่บวกต่อแล้วค่อยตรวจยอดปลายทาง try_fold ทำให้กฎหยุดอยู่ข้าง accumulator จึงอ่าน intent ง่ายกว่า mutable loop ที่มี break หลายจุด
HOW: ให้ accumulator อยู่ใน Result
fn sum_until_negative(values: &[i32]) -> Result<i32, &'static str> {
values.iter().copied().try_fold(0, |sum, value| {
if value < 0 {
Err("negative value")
} else {
Ok(sum + value)
}
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sums_valid_values() {
assert_eq!(sum_until_negative(&[2, 3, 5]), Ok(10));
}
#[test]
fn stops_on_invalid_value() {
assert_eq!(sum_until_negative(&[2, -1, 100]), Err("negative value"));
}
}
เวลาเป็น Result closure ใช้ ? เรียกฟังก์ชันที่อาจพลาดได้ต่อเนื่อง ส่วนงานค้นหาที่อยากคืน None ก็ใช้ Option เป็นตัวควบคุมการหยุดได้ จุดเด่นไม่ใช่โค้ดสั้นอย่างเดียว แต่คือชนิด return บอกชัดว่าการสะสมอาจจบก่อนครบ
ข้อแลกเปลี่ยนคือ try_fold เหมาะเมื่อมี accumulator เดียวและทางหยุดชัด ถ้าต้องอัปเดตหลาย state, เก็บ diagnostic หลายรายการ หรือ recover แล้วเดินต่อ loop ปกติอาจตรงกว่า อย่าบีบทุก state machine เข้า closure เดียวจนอ่านยาก
Recap
- ใช้
try_foldเมื่อการสะสมอาจหยุดด้วยResultหรือOption - วาง validation ไว้ใกล้จุดรวมค่า
- ได้ short-circuit โดยไม่เดินสมาชิกที่เหลือ
- เลือก loop ปกติเมื่อ state และ recovery ซับซ้อน