ชุมชนโปรแกรมเมอร์ Rust กำลังคึกคักไปด้วยการอภิปรายเกี่ยวกับชุดของการแสดงออกที่ผิดปกติและสับสนซึ่งระบบประเภทข้อมูลที่ทรงพลังของภาษานี้อนุญาตให้ใช้ได้ แม้ว่าการแสดงออกเหล่านี้จะเป็นโค้ด Rust ที่ถูกต้องทางเทคนิค แต่พวกมันแสดงให้เห็นมุมที่ลึกลับและซับซ้อนของภาษาที่สามารถทำให้แม้แต่นักพัฒนาที่มีประสบการณ์ก็รู้สึกงุนงง
ธรรมชาติของการออกแบบที่ให้ความสำคัญกับ Expression
สาเหตุหลักของโค้ดแปลกๆ เหล่านี้อยู่ที่ปรัชญาการออกแบบพื้นฐานของ Rust ภาษานี้ถือว่าเกือบทุกอย่างเป็น expression ที่คืนค่า - บล็อก, คำสั่ง if, match expression และแม้กระทั่งแมโคร สิ่งนี้สร้างระบบที่ expression สามารถประกอบกันได้อย่างไม่มีที่สิ้นสุด นำไปสู่โค้ดที่ถูกต้องทางไวยากรณ์แต่แปลกประหลาดทางความหมาย
พวกมันมีอยู่เพราะทั้งภาษาถูกสร้างขึ้นมาเพื่อถือว่า expression เป็นพลเมืองชั้นหนึ่ง : บล็อก, if, match และแม้กระทั่งแมโครเป็น expression ที่คืนค่า ดังนั้นเมื่อคุณเข้าใจสิ่งนี้แล้ว การเขียนโค้ดแปลกๆ แบบบรรทัดเดียวเหล่านี้ก็เป็นเพียงผลพลอยได้
ตัวเลือกการออกแบบนี้หมายความว่าเมื่อนักพัฒนาสำรวจระดับที่ลึกขึ้นของ syntax tree ของ Rust พวกเขาจะพบกับโครงสร้างที่รู้สึกผิดตามสัญชาตญาณแต่เป็นที่ยอมรับได้อย่างสมบูรณ์สำหรับคอมไพเลอร์
มุมมองของชุมชนเกี่ยวกับความสามารถในการอ่าน
น่าสนใจที่ expression แปลกๆ เหล่านี้ไม่ได้สับสนเฉพาะผู้เริ่มต้นเท่านั้น นักพัฒนา Rust ที่มีประสบการณ์ก็ยังพบว่าพวกมันท้าทายในการแยกแยะ ชุมชนยอมรับว่าแม้แต่โปรแกรมเมอร์ที่มีประสบการณ์ก็ต้องใช้เวลาในการเข้าใจสิ่งที่เกิดขึ้นในรูปแบบโค้ดที่ผิดปกติเหล่านี้
การแสดงออกเหล่านี้มีตั้งแต่การกำหนดค่าประเภท unit อย่างง่ายเช่น let () = ();
ไปจนถึงสถานการณ์ที่ซับซ้อนกว่าที่เกี่ยวข้องกับประเภท never (!
) และการคำนวณที่แยกออกไป ตัวอย่างบางส่วนรวมถึงฟังก์ชันที่ไม่เคยคืนค่า, ลูปที่ break ด้วยค่า unit และ closure ที่ใช้ในบริบทที่ไม่คาดคิด
ตัวอย่างของ Expression แปลกๆ ใน Rust
ประเภท Expression | ตัวอย่าง | คำอธิบาย |
---|---|---|
การกำหนดค่า Unit Type | let () = (); |
กำหนด unit type ให้กับ pattern ของ unit type |
ตัวแปร Never Type | let x: ! = loop { continue; }; |
ตัวแปรประเภท never type ที่มีลูปไม่สิ้นสุด |
การ Return แบบ Diverging | let x: ! = { return; }; |
คำสั่ง return ในบริบทของ never type |
Loop พร้อม Break | let x = { loop { break; } }; |
ลูปที่ break ทันที คืนค่าเป็น unit type |
การ Match แบบ Range | match x { 1..=5 => ... } |
การ pattern matching ด้วย inclusive ranges |
การ Match กับ Closure | match closure(5) { 6 => ... } |
การ matching กับค่าที่ closure คืนกลับมา |
บริบททางประวัติศาสตร์และวิวัฒนาการ
การอภิปรายนี้ยังได้เปิดเผยอัญมณีทางประวัติศาสตร์บางอย่างจากการพัฒนา Rust สมาชิกชุมชนคนหนึ่งได้แบ่งปันตัวอย่างโปรดที่เกี่ยวข้องกับฟังก์ชันที่เรียกว่า evil_lincoln()
ซึ่งย้อนกลับไปถึง Rust เวอร์ชันเก่าแก่มาก ตัวอย่างนี้เดิมใช้คีย์เวิร์ด log
(ซึ่งมาก่อนแมโคร println!
) และถูกออกแบบมาเป็นเรื่องตลกที่อ้างอิงถึงของเล่น Lincoln Logs แม้ว่าอารมณ์ขันจะหายไปเมื่อภาษาพัฒนาไป
ผลกระทบในทางปฏิบัติ
แม้ว่า expression เหล่านี้จะทำให้เกิดการทดสอบ parser ที่น่าสนใจ แต่พวกมันมีค่าในทางปฏิบัติจำกัดในโค้ดในโลกจริง ส่วนใหญ่ไม่มีประโยชน์นอกจากการแสดงให้เห็นความยืดหยุ่นและบางครั้งพฤติกรรมที่ไม่คาดคิดของระบบประเภทข้อมูลของ Rust บางอย่างอาจพบการใช้งานในการแข่งขัน code golf แต่โดยทั่วไปจะหลีกเลี่ยงในโค้ดที่ใช้ในการผลิตเพื่อความสามารถในการอ่าน
การอภิปรายนี้เน้นย้ำถึงแง่มุมสำคัญของการออกแบบภาษา: ความสมดุลระหว่างการแสดงออกและความชัดเจน ระบบประเภทข้อมูลที่ทรงพลังของ Rust ทำให้โครงสร้างเหล่านี้เป็นไปได้ แต่ชุมชนโดยทั่วไปเห็นพ้องกันว่าเพียงเพราะสิ่งใดสิ่งหนึ่งเป็นไปได้ไม่ได้หมายความว่าควรใช้ในการเขียนโปรแกรมในชีวิตประจำวัน
การสนทนาที่กำลังดำเนินอยู่นี้สะท้อนถึงความมุ่งมั่นของชุมชน Rust ในการเข้าใจภาษาของพวกเขาอย่างลึกซึ้งในขณะที่ยังคงมุ่งเน้นไปที่โค้ดที่ใช้งานได้จริงและอ่านง่ายซึ่งตอบสนองแอปพลิเคชันในโลกจริง
อ้างอิง: Weird expressions in rust