ข้อผิดพลาดของ Swift Compiler: เคส enum มี tuple เดียวเป็นค่าที่เกี่ยวข้อง แต่มีหลายรูปแบบที่นี่


12

สร้างโครงการใน Xcode 11.4 เบต้า 3 ฉันได้รับข้อผิดพลาด Swift Compiler นี้ใน enum:

เคส enum มี tuple เดียวเป็นค่าที่เกี่ยวข้อง แต่มีหลายรูปแบบที่นี่โดยปริยาย tupling รูปแบบและพยายามจับคู่แทน

รหัสแหล่งที่มา:

switch result {
case .error(let err):
    //
case .value(let staff, let locations):  // <-- error on this line
    //
}

Resultเป็น enum ทั่วไปที่มีค่าที่เกี่ยวข้องสำหรับการและ.error .valueในกรณีนี้ค่าที่เกี่ยวข้องคือ tupple

public enum Result<T> {
    case value(T)
    case error(Error)
}

อย่าจำได้ว่าเคยเห็นข้อผิดพลาดนี้มาก่อนและการค้นหามันไม่ได้ให้ผลลัพธ์ใด ๆ ความคิดใด ๆ


1
ฉันอัปเดตคำถามขอโทษที่ออกจากนั้น
Eneko Alonso

ไม่จำเป็นต้องบูรณาการผลล้อ; มันมีอยู่แล้ว developer.apple.com/documentation/swift/result
matt

นอกจากนี้ยังไม่มี Xcode 11.4 เบต้า 4 (ยัง)
แมตต์

ที่ไม่ดีของฉันฉันหมาย Xcode 11.4 เบต้า 3. ในเรื่องที่เกี่ยวกับผมเห็นมันเป็นรหัสเดิมที่ถือกำเนิดResult Swift.Resultที่ไม่เกี่ยวข้องกับปัญหาแม้ว่า
Eneko Alonso

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

คำตอบ:


14

ฉันพบว่าคุณสามารถเงียบข้อผิดพลาดนี้ได้โดยรักษาค่าที่เกี่ยวข้องมากขึ้นเช่น tuple โดยห่อไว้ในวงเล็บชุดพิเศษ:

switch result {
case .error(let err):
    //
case .value((let staff, let locations)):  
    //
}

1
นั่นเป็นสิ่งที่ดีฉันชอบมันขอบคุณ
Eneko Alonso

2
ลองพิจารณาการย้ายletออกหากคุณจะผูกทุกอย่างไว้: case let .value( (staff, locations) ):และcase .value( let (staff, locations) ):รวบรวมทั้งคู่ เลือกสิ่งที่คุณโปรดปราน!
Jessy

1
ผู้เยาว์สุด แต่ฉันไม่เห็นด้วยกับความคิดเห็นข้างต้นเกี่ยวกับการผูกทุกอย่างด้วยการอนุญาตเพียงครั้งเดียว การให้ด้านซ้ายของสิ่งที่ถูกผูกไว้ง่ายต่อการอ่านและเข้าใจสิ่งที่ถูกผูกไว้อย่างรวดเร็ว มิฉะนั้นคุณต้องคาดการณ์ทางจิตใจว่าการเชื่อมโยงนั้นมีผลผูกพันอะไร แนวทางการเขียนโปรแกรมของ Google สำหรับรวดเร็วนอกจากนี้ยังให้คำแนะนำกับซ้อนเดียวให้: google.github.io/swift/#pattern-matching
ToddH

2
หลักเกณฑ์ "ของ Google": /
Gee.E

9

ตกลงคิดออก ดูเหมือนว่าenumมีค่าที่เกี่ยวข้องซึ่งประเภทของค่าเป็นทัปเปอร์ไม่สามารถจับคู่กับคำสั่งเปลี่ยนเช่นนั้น:

// Works on Xcode 11.3.1, yields error on 11.4 (Swift 5.2)
switch result {
case .error(let err):
    //
case .value(let staff, let locations):  
    //
}

สารละลาย

ค่าจาก tupple ต้องถูกแยกด้วยตนเองใน Xcode 11.4 (Swift 5.2):

// Works on Xcode 11.4
switch result {
case .error(let err):
    //
case .value(let tupple):  
    let (staff, locations) = tupple
    // 
}

นั่นเป็นทางออกหนึ่งอย่างแน่นอน
แมตต์

3

นี่เป็นปัญหาที่ทราบแล้ว: https://developer.apple.com/documentation/xcode_release_notes/xcode_11_4_release_notes

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

ตัวอย่างเช่นการไม่ใส่วงเล็บออกเมื่อเปิดใช้ตัวเลือกชนิด tuple ทำให้เกิดข้อผิดพลาดของคอมไพเลอร์:

switch x { // error: switch must be exhaustive
case .some((let a, let b), let c): // warning: the enum case has a
     // single tuple as an associated value, but there are several
     // patterns here, implicitly tupling the patterns and trying
     // to match that instead
...

}

วิธีแก้ปัญหา : เพิ่มวงเล็บพิเศษเพื่อเพิ่มรูปแบบให้ชัดเจน:

switch x {
case .some(((let a, let b), let c)): // Notice the extra pair of parentheses.
...

}


ขอบคุณสำหรับข้อมูลเพิ่มเติมและลิงก์ไปยังบันทึกประจำรุ่น ฉันคิดถึงสิ่งนั้น
Eneko Alonso

0

ถ้าฉันอาจฉันต้องการเพิ่มคำตอบสำหรับif caseรุ่นด้วย

if case let .value(staff, error) = result {
    // Do something
}

และแน่นอนกรณีที่ไม่สนใจ:

if case let .value(staff, _) = result {
    // Do something
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.