ปูสีส้มแดงต้นฉบับหยุดสายพานสะสมทันทีเมื่อพบชิ้นงานสีอำพันแตกร้าว

Rust try_fold: สะสมค่าแล้วหยุดทันทีเมื่อเจอเงื่อนไขผิด

พี่โชว์Engineering

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 ซับซ้อน