เครื่องหมายคำถามนี้เกี่ยวกับอะไร?


98

ฉันกำลังอ่านเอกสารสำหรับFile :

//..
let mut file = File::create("foo.txt")?;
//..

อะไรคือสิ่งที่?อยู่ในแนวเดียวกันนี้หรือไม่? ฉันจำไม่ได้ว่าเคยเห็นมันใน Rust Book มาก่อน


สังเกตว่าคำอธิบายของ? ได้รับการบรรจุในหนังสือ 2018 doc.rust-lang.org/edition-guide/rust-2018/…
Patrik Stas

คำตอบ:


145

ดังที่คุณอาจสังเกตเห็น Rust ไม่มีข้อยกเว้น มีอาการตื่นตระหนก แต่ฟังก์ชันการทำงานมี จำกัด (ไม่สามารถนำข้อมูลที่มีโครงสร้างได้) และไม่แนะนำให้ใช้เพื่อจัดการข้อผิดพลาด (มีไว้สำหรับข้อผิดพลาดที่ไม่สามารถกู้คืนได้)

ใน Rust Resultจัดการข้อผิดพลาดการใช้งาน ตัวอย่างทั่วไปจะเป็น:

fn halves_if_even(i: i32) -> Result<i32, Error> {
    if i % 2 == 0 {
        Ok(i / 2)
    } else {
        Err(/* something */)
    }
}

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = match halves_if_even(i) {
        Ok(i) => i,
        Err(e) => return Err(e),
    };

    // use `i`
}

สิ่งนี้ยอดเยี่ยมเพราะ:

  • เมื่อเขียนโค้ดคุณจะไม่ลืมจัดการกับข้อผิดพลาดโดยไม่ได้ตั้งใจ
  • เมื่ออ่านโค้ดคุณจะเห็นได้ทันทีว่ามีโอกาสเกิดข้อผิดพลาดที่นี่

อย่างไรก็ตามมันน้อยกว่าอุดมคติ แต่มันเป็นเรื่องฟุ่มเฟือยมาก นี่คือที่?มาของตัวดำเนินการเครื่องหมายคำถาม

ข้างต้นสามารถเขียนใหม่เป็น:

fn do_the_thing(i: i32) -> Result<i32, Error> {
    let i = halves_if_even(i)?;

    // use `i`
}

ซึ่งกระชับกว่ามาก

สิ่ง?ที่เทียบเท่ากับmatchข้อความข้างต้น กล่าวโดยย่อ: มันจะเปิดกล่องResultif OK และส่งคืนข้อผิดพลาดหากไม่

มันเป็นความมหัศจรรย์เล็กน้อย แต่จัดการข้อผิดพลาดความต้องการความมหัศจรรย์บางอย่างที่จะตัดลงสำเร็จรูปและแตกต่างจากข้อยกเว้นมันจะมองเห็นได้ทันทีซึ่งฟังก์ชั่นการโทรหรืออาจจะไม่เกิดข้อผิดพลาดออก: ?ผู้ที่จะประดับด้วย

ตัวอย่างหนึ่งของเวทมนตร์คือสิ่งนี้ใช้ได้กับOption:

// Assume
// fn halves_if_even(i: i32) -> Option<i32>

fn do_the_thing(i: i32) -> Option<i32> {
    let i = halves_if_even(i)?;

    // use `i`
}

นี้เป็นที่ขับเคลื่อนโดย (ไม่แน่นอน) Tryลักษณะ

ดูสิ่งนี้ด้วย:


5
มันจะดีหากคุณสามารถขยายคำตอบของคุณนิด ๆ หน่อย ๆ เช่นหารือว่าประเภทการกลับมาของฟังก์ชั่นจะต้องตรงกับประเภทที่คุณพยายามที่จะ "แกะ" เช่นหรือResult Option
hellow

@hellow ฉันเดาว่าน่าจะเป็นคำถามใหม่ทั้งหมด
Paul Razvan Berg

2

สำหรับการเผยแพร่ข้อผิดพลาดสำหรับประเภทข้อผิดพลาดที่กู้คืนได้ผลลัพธ์ <T, E> มันแกะผลลัพธ์และให้คุณค่าภายในแก่คุณ

แทนที่จะจัดการกรณีข้อผิดพลาดคุณเผยแพร่ไปยังรหัสผู้โทรและจัดการเฉพาะกรณีตกลง ข้อดีคือช่วยกำจัดหม้อไอน้ำจำนวนมากและทำให้การใช้งานฟังก์ชันง่ายขึ้น


เพื่อไม่ให้สับสนกับความ.unwrap()ตื่นตระหนกในกรณีที่เกิดข้อผิดพลาด
จอร์แดน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.