- ในด้านการจัดการหน่วยความจำ Zig มอบแนวทางที่เรียบง่ายและตรงไปตรงมากว่า Rust
- borrow checker ของ Rust แม้จะทรงพลัง แต่สำหรับการพัฒนาเครื่องมือ CLI ขนาดเล็กกลับสร้างความซับซ้อนเกินจำเป็นและเพิ่มภาระให้ผู้พัฒนา
- การจัดการหน่วยความจำแบบแมนนวลของ Zig ทำให้สามารถบรรลุความปลอดภัยของหน่วยความจำได้อย่างมีประสิทธิภาพ ด้วยเครื่องมือที่เหมาะสมและวินัยของนักพัฒนาเพียงเล็กน้อย
- ความปลอดภัยของโปรแกรมไม่ได้มีแค่ความปลอดภัยของหน่วยความจำเท่านั้น แต่ยังรวมถึงพฤติกรรมที่คาดเดาได้ ประสิทธิภาพที่ควบคุมได้ และการปกป้องข้อมูลด้วย
- Rust เหมาะกับระบบขนาดใหญ่ แต่สำหรับเครื่องมือ CLI ขนาดเล็กที่เน้นการใช้งานจริง Zig ได้เปรียบกว่าในด้านประสิทธิภาพการพัฒนาและการดูแลรักษา
ภาพรวม
ช่วงหลังมานี้เวลาสร้างเครื่องมือ CLI มักเลือก Zig ก่อน Rust
พื้นฐานของการจัดการหน่วยความจำ: สแตกและฮีป
- สแตกเป็นพื้นที่หน่วยความจำแบบขนาดคงที่ที่รวดเร็ว ใช้เก็บข้อมูลชั่วคราวมาก เช่น พารามิเตอร์ของฟังก์ชัน ตัวแปรภายใน และที่อยู่สำหรับการคืนค่า
- ฮีปเป็นพื้นที่สำหรับการจัดสรรหน่วยความจำแบบไดนามิก ใช้เมื่อข้อมูลมีอายุยาวขึ้นหรือมีขนาดที่ตัดสินได้ตอนรันไทม์
- สแตกมีโครงสร้างเรียบง่าย แต่พื้นที่จำกัด ส่วนฮีปมีเรื่องความเร็วและการกระจัดกระจายของหน่วยความจำที่ต้องใส่ใจ
Borrow Checker ของ Rust
- borrow checker ของ Rust รับประกันความปลอดภัยของหน่วยความจำในขั้นคอมไพล์
- มันบังคับใช้กฎอย่างการอ้างอิง ความเป็นเจ้าของ และ lifetime เพื่อป้องกันข้อผิดพลาดอย่างการ dereference null pointer หรือ dangling pointer ตั้งแต่ก่อนรันจริง
- อย่างไรก็ตาม การตรวจสอบความปลอดภัยของหน่วยความจำนี้เกิดขึ้นเฉพาะในระดับคอมไพล์ และไม่ได้ช่วยขจัดความผิดพลาดของผู้ใช้หรือปัญหาการออกแบบ ownership ที่ซับซ้อนออกไปได้ทั้งหมด
กรณีศึกษา: Notes CLI ของฉันเอง
- ตอนพยายามเขียน CLI สำหรับจัดการโน้ตส่วนตัวด้วย Rust ต้องฝืนออกแบบโครงสร้างใหม่เพราะborrow checker
- ในทางกลับกัน Zig สามารถใช้แค่ allocator เพื่อสร้างดัชนีแบบอิง pointer และแก้ไขหรือลบข้อมูลได้อย่างอิสระและเรียบง่ายกว่ามาก
- borrow checker ของ Rust มีเป้าหมายที่ชัดเจน แต่ Zig ก็สามารถบรรลุประสิทธิภาพและความปลอดภัยในระดับสูงได้เช่นกัน ด้วยเพียงความรู้พื้นฐานเรื่องการจัดการหน่วยความจำและวินัยในการพัฒนา
ความปลอดภัยของเครื่องมือ CLI ไม่ได้มีแค่ความปลอดภัยของหน่วยความจำ
- ความปลอดภัยที่แท้จริงของโปรดักต์ครอบคลุมองค์ประกอบหลากหลาย เช่น พฤติกรรมที่คาดเดาได้ การตอบกลับที่มีความหมายเมื่อเกิดข้อผิดพลาด การปกป้องข้อมูลอ่อนไหว และความทนทานต่อการโจมตี
- ไม่ว่าจะเป็น Rust หรือ Zig ถ้าไม่ตอบโจทย์เงื่อนไขนอกเหนือจากความปลอดภัยของหน่วยความจำ ก็ยังไม่อาจเรียกว่า "ปลอดภัย" ได้
- ตัวอย่างเช่น ถ้า CLI เขียนทับข้อมูลแบบเงียบ ๆ เมื่อเกิดข้อผิดพลาด หรือกำหนดสิทธิ์ไฟล์ผิด ผู้ใช้อาจเจอปัญหาร้ายแรงได้
-
ความปลอดภัยของเครื่องมือ CLI
- พฤติกรรมที่คาดเดาได้: ต้องรับประกันการทำงานที่สม่ำเสมอและชัดเจนแม้ได้รับอินพุตที่ผิดหรือเจอสถานการณ์ไม่คาดคิด
- การป้องกันการล่มและข้อมูลเสียหาย: ต้องจัดการข้อผิดพลาดอย่างเหมาะสม และป้องกันข้อมูลเสียหายหรือการล่มที่ไม่ถูกแจ้ง
- การจัดการประสิทธิภาพ: แม้ประมวลผลข้อมูลจำนวนมากก็ไม่ควรใช้ทรัพยากรเกินจำเป็นหรือทำให้การตอบสนองลดลง
- การปกป้องข้อมูลอ่อนไหว: ต้องระวังไฟล์ชั่วคราวและการตั้งค่าสิทธิ์
- ความทนทานต่อการโจมตี: ต้องแข็งแรงต่อการตรวจสอบอินพุต, memory overflow, การโจมตีแบบ injection เป็นต้น
จุดแข็งและข้อจำกัดของ Rust Borrow Checker
-
จุดแข็ง
- ป้องกัน data race และการอ้างอิงซ้ำซ้อน: คอมไพเลอร์รับประกันกติกาเรื่อง mutable reference เดี่ยวและ immutable reference หลายตัว
- การรับประกันอันแข็งแกร่งในขั้นคอมไพล์: บั๊กด้านหน่วยความจำส่วนใหญ่ถูกป้องกันก่อนรันโปรแกรม
- ค้นพบบั๊กได้ตั้งแต่ระยะแรก: เป็นข้อได้เปรียบมากในบริการเชิงพาณิชย์หรือระบบที่มี concurrency
-
ข้อจำกัดและความไม่สะดวก
- ภาระทางความคิด: แม้เป็นงาน CLI เล็ก ๆ ก็ยังต้องคอยคิดเรื่อง ownership/lifetime/reference อยู่เสมอ
- boilerplate/ความบิดเบี้ยวของโครงสร้าง: wrapper อย่าง Rc, RefCell, การใช้
cloneมากเกินไป หรือการออกแบบโครงสร้างใหม่ ทำให้โฟกัสกลายเป็นการ "ทำให้คอมไพเลอร์พอใจ" แทนที่จะเป็นการ "แก้ปัญหา" - รับมือกับบั๊กเชิงตรรกะหรือสถานะไม่ได้: มันรับประกันแค่กฎด้านหน่วยความจำ แต่ไม่ได้รับประกันความคาดเดาได้ ความผิดพลาดเชิงตรรกะ หรือความสมบูรณ์ของข้อมูล
- ความซับซ้อนใน edge case: ในกรณีอย่างแคช สถานะโกลบอล หรือ mutable index มักเกิดการชนกันของ lifetime ได้ง่าย
- ผลลัพธ์คือ ในโปรเจกต์ CLI ขนาดเล็ก borrow checker ของ Rust กลายเป็น "ภาษีทางจิตใจ" สำหรับนักพัฒนา และอาจทำให้ระบบซับซ้อนเกินความจำเป็นจริง
แนวทางของ Zig ต่อความปลอดภัยและความเรียบง่าย
- Zig ใช้พื้นฐานเป็นการตรวจสอบความปลอดภัยแบบเลือกได้และการจัดการหน่วยความจำแบบแมนนวล
- ภาษานี้มีแนวคิดเรื่อง allocator มาในตัว ทำให้สามารถออกแบบการใช้หน่วยความจำได้อย่างมีโครงสร้างและคาดเดาได้
- ยังสามารถสร้าง custom allocator เพื่อกำหนดรูปแบบการจัดการหน่วยความจำให้เหมาะกับลักษณะของโปรเจกต์ได้ด้วย
- ด้วยไวยากรณ์
deferของ Zig การปล่อยทรัพยากรอัตโนมัติและการทำความสะอาดทรัพยากรเมื่อออกจากสโคปจึงตรงไปตรงมาอย่างมาก - ต่างจาก Rust ที่เน้นข้อบังคับอย่างหนัก Zig เน้นความรับผิดชอบของนักพัฒนามากกว่า จึงต้องมีวินัย แต่ถ้าออกแบบโครงสร้างให้ดี ก็ทำให้บรรลุและรักษาความปลอดภัยของหน่วยความจำได้ง่าย
- Zig มีโค้ดที่กระชับกว่า และการเปลี่ยนโครงสร้างอย่าง pointer, list, index ต่าง ๆ ก็ง่ายกว่า Rust มาก
- สามารถเขียนโค้ดที่ปลอดภัยและมีประสิทธิภาพในระดับเดียวกันได้ โดยไม่ต้องถูกผูกมัดแบบ Rust
- นอกจากนี้ ฟีเจอร์ comptime ของ Zig ยังช่วยมากในด้านการรันโค้ด การทดสอบ และการปรับแต่งประสิทธิภาพในขั้นคอมไพล์
ความสำคัญของประสบการณ์นักพัฒนา (Developer Ergonomics)
- ประสบการณ์นักพัฒนา (ergonomics) ครอบคลุมตั้งแต่ไวยากรณ์ของภาษา เครื่องมือ เอกสาร ไปจนถึงชุมชน
- Rust แม้จะรับประกันความปลอดภัยของหน่วยความจำได้อย่างยอดเยี่ยมด้วยกฎอันเข้มงวด แต่กฎและ ceremony ที่มากเกินไปก็ลดทอนประสิทธิภาพการทำงาน
- Zig เน้นการออกแบบที่ขับเคลื่อนโดยผู้พัฒนา ทำให้เขียน แก้ไข และทำความเข้าใจโค้ดได้ง่ายและรวดเร็วกว่า
- Zig ช่วยให้นักพัฒนามุ่งกับการแก้ปัญหาแทนการต่อสู้กับเครื่องมือ ด้วยโค้ดที่เข้าใจง่าย การวนรอบพัฒนาเร็ว และภาระทางความคิดที่ต่ำ
- Zig ไว้วางใจนักพัฒนาและมอบเครื่องมือกับทางเลือกที่เหมาะสม ขณะที่ Rust อาจให้ความรู้สึกว่าควบคุมเข้มงวดและจำกัดมากเกินไป
- แทนที่จะ "ปกป้องนักพัฒนาจากความผิดพลาด" การเปิดโอกาสให้เรียนรู้และพัฒนาผ่านความผิดพลาดของตนเองต่างหากที่เป็นสภาพแวดล้อมที่เป็นมิตรต่อนักพัฒนา
บทสรุป
- ในงานอย่างระบบขนาดใหญ่ แบบมัลติเธรด หรือทำงานระยะยาวซึ่งเป็นจุดที่ข้อดีของ Rust โดดเด่นที่สุดนั้น Rust ยังเป็นตัวเลือกที่ยอดเยี่ยมที่สุด
- แต่สำหรับเครื่องมือ CLI ขนาดเล็กที่เน้นการใช้งานจริง ความเบา ความเรียบง่าย และการพัฒนา/ดูแลรักษาที่รวดเร็วของ Zig เหมาะสมกว่า
- ความปลอดภัยของหน่วยความจำเป็นเพียงส่วนหนึ่งของจิ๊กซอว์เรื่องความปลอดภัยเท่านั้น ส่วนองค์ประกอบสำคัญต่อเครื่องมือ CLI อย่างพฤติกรรมที่คาดเดาได้ การบำรุงรักษาง่าย และความทนทานนั้น Zig ทำได้ง่ายกว่า
- ท้ายที่สุด สิ่งสำคัญไม่ใช่การหา "ภาษาที่ดีกว่า" แต่คือการเลือก "เครื่องมือ" ที่เหมาะกับ workflow และลักษณะของโปรเจกต์ของเรา
- Zig คือภาษาที่ลงตัวอย่างยิ่งสำหรับการพัฒนาเครื่องมือขนาดเล็ก เพราะผสาน "ความปลอดภัยของหน่วยความจำ + ต้นทุนทางความคิดต่ำ + ความเป็นมิตรต่อผู้พัฒนา/ประสิทธิภาพการทำงาน" เข้าไว้ด้วยกัน
3 ความคิดเห็น
ดูเหมือนว่าระบบนิเวศของมันยังไม่เสถียรเท่า Rust นะครับ
เนื่องจาก Zig มีการเปลี่ยนแปลงที่ทำให้เข้ากันไม่ได้บ่อยมากในเวอร์ชันใหม่ ๆ ... ต่อให้เป็นโปรเจ็กต์เล็กก็คงต้องพยายามผูก ci ไว้แล้วคอยดูแลต่อเนื่องกันไปครับ
ความเห็นจาก Hacker News
ข้อดีของ Zig คือมันทำให้ยังคิดแบบนักพัฒนา C ต่อไปได้ แต่ในระดับหนึ่งก็คิดว่าเป็นเรื่องของความคุ้นเคยล้วน ๆ
นักพัฒนาที่คุ้นกับ Rust มากพอแล้วจะไม่ต้องสู้กับ borrow checker อีก เพราะจะคิดเป็นโครงสร้างโค้ดแบบนั้นไปแล้ว
แนวทางแบบ “object soup” ใน Rust ใช้ได้ไม่ค่อยดี แต่ก็ไม่ได้คิดว่านั่นเป็นวิธีที่ง่ายกว่าโดยพื้นฐาน เพียงแค่เราคุ้นเลยรู้สึกว่ามันง่าย
ถ้ายอมรับสมมติฐานว่า ergonomics (ประสบการณ์การใช้งาน) วัดหรือทำให้เป็นตัวเลขได้ยาก การถกเถียงแบบนี้ก็จะกำกวมต่อไป
เรื่อง “การสู้กับ borrow checker” มีที่มาจากยุคที่เข้าใจแค่ lexical lifetime ใน Rust
จากประสบการณ์ของฉัน นักพัฒนา Rust ที่ชำนาญมักโปรย Arc ไว้ทั่ว ๆ เพื่อใช้มันคล้าย garbage collection แบบอัตโนมัติ
ฉันก็เห็นโปรเจกต์ Rust โอเพนซอร์สมากมายที่แม้แต่นักพัฒนาชำนาญก็ยังใช้ Arc, Clone, Copy ฯลฯ กระจายอยู่เต็มไปหมด
ข้อดีของ Zig คือยังพัฒนาแบบคุ้นมือเหมือน C ได้ แต่ภาษากับ tooling ก็มีฟีเจอร์ช่วยเรื่องความปลอดภัย
ฉันไม่เห็นด้วยกับเนื้อหาต้นฉบับเกือบทั้งหมด
Rust ก็ทำให้ต้องคิดเรื่อง lifetime, ownership, และ borrow scope เหมือน C หรือ Zig ความต่างคือมีหรือไม่มีตัวช่วยจากคอมไพเลอร์
ต่อให้ฉลาดแค่ไหน มนุษย์ก็พลาดได้เวลาเหนื่อยหรือลังเล การยอมรับว่าตัวเองพลาดได้ต่างหากคือความฉลาด
พื้นที่ของโปรแกรมที่คอมไพเลอร์ Rust ถือว่าปลอดภัยนั้นกว้างไม่พอ จึงปฏิเสธโปรแกรมที่ปกติใช้ได้อยู่บ่อยพอสมควร
ตัวอย่าง: ถ้าใน struct
Fooมีbarกับbazเป็นสตริงคนละตัว แล้วพยายามทำ mutable reference กับbarและ immutable reference กับbazก็จะคอมไพล์ไม่ผ่าน ทำให้ในสถานการณ์แบบนี้ต้องบิดโครงสร้างโค้ดเพื่อเลี่ยงปัญหาถ้าจะโต้แย้งกลับ ภาระที่ต้องเปลี่ยนโค้ดไปเป็นดีไซน์ที่ดีรองหรือดีอันดับสามเพียงเพื่อ “หลีกเลี่ยงกรณีที่จริง ๆ แล้วถูกต้องแต่คอมไพเลอร์ปฏิเสธ” นั้นหนักมาก
ตัวอย่างข้างบนดูเป็นกรณีศึกษาที่ยอดเยี่ยมมาก อยากถามว่านำไปพูดถึงในบล็อกหรือบทความของฉันได้ไหม
พอดูโค้ดข้างบนแล้วกลับยิ่งไม่มั่นใจกับข้ออ้างนั้นมากขึ้น
เราควรจำไว้ว่าไม่ใช่ทุกโปรแกรมที่จะต้อง “ปลอดภัย” แบบนั้นเสมอไป
พวกเราหลายคนก็เติบโตมากับการสนุกกับซอฟต์แวร์ Unsafe มากมาย เช่น Star Fox 64, MS Paint, FruityLoops
เคยอ่านมาว่า Andrew Kelley ผู้สร้าง Zig ทำ Zig ขึ้นมาเพราะไม่มีสภาพแวดล้อมพัฒนาสำหรับซอฟต์แวร์ทำเพลง (DAW) และคิดว่า Zig เหมาะกับซอฟต์แวร์เชิงสร้างสรรค์แบบนั้นมาก
ถ้าใครกังวลเรื่อง memory bug ก็ใช้ Rust ไปได้เลย
ฉันเชื่อว่า Super Mario World ก็สนุกขึ้นเพราะ memory bug ด้วยเหมือนกัน
“ความปลอดภัย” คือคำย่อของ “โปรแกรมของฉันทำงานตามที่ตั้งใจไว้”
unsafe)ฉันสับสนเล็กน้อย เลยสงสัยว่าเหตุผลที่คิดว่าความเห็นของฉันแย่คือคุณหมายความว่า memory safety ไม่สำคัญหรือเปล่า
รู้สึกเสียดายที่คุณค่าของ borrow checker ถูกประเมินต่ำเกินไป
borrow checker ของ Rust รับประกันการเข้าถึงหน่วยความจำที่ถูกต้องไม่ได้ตั้งแต่ตอนคอมไพล์
แน่นอนว่ามันก็มาพร้อมความไม่สะดวกที่ต้องเปลี่ยนโครงสร้างโค้ดให้สอดคล้องกับกฎของคอมไพเลอร์
ตอนที่ฉันใช้ Rust เองโดยตรง ไม่เคยรู้สึกว่า lifetime annotation นั้น “ผิด” แม้มันจะดูเป็นงานจุกจิกน่ารำคาญอยู่บ้าง แต่ก็ชินได้เร็ว
ตราบใดที่ไม่ใช้
unsafeใน Rust จะไม่มีสองเธรดมาเขียนหน่วยความจำเดียวกันพร้อมกันได้ฉันไม่ค่อยเข้าใจประเด็น “ทำไม Zig ถึงรู้สึกใช้งานจริงกว่าในเครื่องมือ CLI” เพราะ Rust ก็ยังได้เปรียบในด้านป้องกัน CVE (ช่องโหว่)
จริง ๆ แล้วฉันทำงานส่วนใหญ่ด้วยภาษา GC ก็พออยู่แล้ว และเวลาจะไปช่วยโปรเจกต์ภาษาอื่นก็ใช้ได้หมดทั้ง Rust, Zig, C/C++
CLI tool มันพิเศษตรงไหนอย่างนั้นหรือ?
การบอกว่าไม่ใช้
unsafeแล้วสองเธรดจะเขียนหน่วยความจำเดียวกันพร้อมกันไม่ได้ มันก็ไม่ได้ชัดเจนสะอาดขนาดนั้นเห็นด้วยว่าการทำ backlinks ใน Rust ซับซ้อนเกินไป
มันทำได้ด้วย
Rc,Weak,RefCell,.borrow()ฯลฯ แต่ก็ไม่ง่ายถ้าเป็นโปรแกรมอายุสั้น การจัดสรรแบบ arena ก็เป็นอีกทางหนึ่งได้ (ซึ่งอาจตรงกับความหมายของ CLI tool)
Rust จะแสดงพลังจริงในแอปพลิเคชันขนาดใหญ่ แบบหลายเธรด และรันยาวนาน
ฉันเคยเขียนเมตาเวิร์สไคลเอนต์ขนาดใหญ่ด้วย Rust จริง ๆ และแม้จะรันหลายสิบเธรดตลอด 24 ชั่วโมงก็ไม่มี memory leak หรือแครชเลย
ถ้าจะทำสิ่งเดียวกันใน C++ ก็คงต้องมีทีม QA กับเครื่องมืออย่าง Valgrind เป็นของจำเป็น และถ้าใช้ภาษาสคริปต์ก็ช้าเกินไปด้านประสิทธิภาพ
ฉันเองก็เคยทำเครื่องบินจำลองฟิสิกส์ด้วย Rust ที่คำนึงถึงทั้งความโค้งของโลกและความแปรผันของแรงโน้มถ่วง
Zig ก็น่าสนใจอยู่ แต่ D ก็ยังมีอยู่ และส่วนตัวรู้สึกว่า D คือสิ่งแทน C/C++ ที่ฉันต้องการ
ไวยากรณ์ของ Zig ดูแปลก ๆ อยู่บ้าง ส่วน Rust ก็กลายเป็นแกนกลางของ ecosystem ไปแล้ว
Go เองก็มีส่วนแบ่งสูงในเครื่องมือหลายอย่าง และในสาย AI ก็เป็นรองแค่ Python ในการใช้งาน
ก่อน Rust จะมาก็เคยมีการถก Go vs. D และฉันเองก็เคยซื้อหนังสือ D มาเรียน ก่อนจะเปลี่ยนใจไปทาง Go
int64ก็ตรงไปตรงมากว่าD ดีอยู่หรอก แต่ยังไม่มี killer app ที่ทำให้แพร่หลาย
ฉันไม่ค่อยเข้าใจว่าทำไมต้องยืนยันจะใช้ Rust หรือ Zig เพื่อทำ CLI tool
คอขวดคือ I/O ไม่ใช่ว่า GC ช้า
ถ้าไม่ใช่งานที่ใช้หน่วยความจำหนักอย่างเกมหรือฐานข้อมูล ฉันคิดว่าประเด็น GC ก็ไม่ใช่ประเด็นหลัก
เลยอยากเน้นว่ามากกว่าการถกเรื่อง memory safety ฉันมักคิดถึงเหตุผลว่าทำไมต้องเลือกภาษาที่ไม่ต้องมี GC
ถ้าเหตุผลคือ “มันสนุกดีที่ไม่มี GC” แค่นั้นก็เพียงพอแล้ว ไม่จำเป็นต้องเถียงกัน
startup time ที่เกิดขึ้นทันทีโดยไม่มีการหน่วงตอนรัน มีประโยชน์มาก
การทำ CLI ด้วย Go ถือว่าโอเคมาก (แม้ว่าจะไม่ได้ชอบภาษา Go เองนัก)
ฉันจะเลือกภาษาที่มี sum type, pattern matching, และรองรับ async เป็นอันดับแรก
สำหรับคำท้วงติงที่ว่าการพัฒนาแบบไม่มี GC ใช้ได้แค่ในสายเกมเท่านั้น
การถกเรื่อง GC ให้ความรู้สึกเหมือนเป็นการแห่ตามกระแสอย่างหนึ่ง
ฉันเคยทำเครื่องมือจดโน้ตง่าย ๆ ด้วย borrow/referencing แบบ built-in ของ Rust และมันไม่ได้ซับซ้อนอย่างที่คิด
ถ้าจินตนาการเป็นโครงสร้างที่เก็บ index ของรายการ
notesแล้วเชื่อมกันด้วย map ความต่างด้านความเร็วก็แทบไม่มี และก็ไม่มีข้อเสียด้านความปลอดภัยด้วยต่อให้พลาดเรื่อง index ก็ยังโดนจับเป็น out-of-bounds error ได้ ดีกว่าเขียนทับ kernel memory มาก
ตอนทำ printf debugging ก็ง่ายและตรงไปตรงมามากกว่า
โดยทั่วไป raw pointer หรือ reference ควรใช้เฉพาะจุดที่จำเป็นจริง ๆ อย่าง allocator หรือ async runtime ส่วน logic ทั่วไปแบบอิง index จะเหมาะกว่า
นี่ก็เป็นเหตุผลที่มีการพูดกันบ่อยว่า Rust async ใช้ self-referential struct ไม่ได้ จึงมีประเด็นเกี่ยวกับ
Pinตามมาpointer ไปยังค่าที่เก็บอยู่ใน
vecจะใช้ไม่ได้ทันทีถ้าเกิดreallocเป็นต้น ซึ่งในกรณีนี้Miriจะรายงาน error ทันทีถ้าฉันเป็นนักพัฒนา C++ ที่กำลังมองหาภาษาปลอดภัย ฉันคงรู้สึกว่า Swift เหมาะที่สุด
ภาษาที่คุ้นเคยหรือคล้ายเดิมจะปรับตัวได้เร็วกว่า
ช่วงหลัง Swift ก็เสริมการรองรับข้ามแพลตฟอร์มมากขึ้น และมีคนจากคณะกรรมการมาตรฐาน C++ ปัจจุบันเข้าร่วมหลายคน
แต่ด้วยความผูกกับ Apple และการไม่มี native UI framework ที่แข็งแรงในโลกนอก Apple การขยายตัวฝั่ง non-Apple จึงยังน้อยกว่า
หวังว่า Swift จะได้รับความนิยมมากขึ้น
ถ้ามีแหล่งข้อมูลที่เปรียบเทียบ Swift กับ Zig/C ได้ก็อยากให้แนะนำ
มีคนพูดว่า Zig ก็ทำซอฟต์แวร์ที่ memory safe ได้ด้วยความระมัดระวังระดับพอเหมาะ แต่จริง ๆ แล้ว C เองถ้าใช้อย่างมีวินัยในระดับหนึ่งก็ให้ผลแบบเดียวกันได้
ท้ายที่สุดปัญหาคือ “วินัย/การฝึกเพียงเล็กน้อย” นี้ไม่เพียงพอในโลกจริง จึงเกิดปัญหาอยู่เสมอ
Zig ยังช่วยแก้ปัญหาเพิ่มเติมเหล่านี้ด้วย
comptime, และเวลา build ที่เร็วกว่า C++/Rust หลายสิบเท่าก็เป็นจุดแข็งถ้า C ล้มเหลวกับปัญหาเรื่อง discipline แบบนี้มานานกว่า 50 ปีแล้ว มันก็คงยากยิ่งกว่า “วิถีเส้าหลิน” เสียอีก