กลับมาใช้ Zig อีกครั้ง - Zig → Rust → Zig
(gracefulliberty.com)- Zig เริ่มต้นในฐานะภาษา low-level ที่พยายามลดความไม่สะดวกของ C และกลายเป็นภาษาที่ควรกลับมาพิจารณาอีกครั้ง ด้วยปรัชญาอย่าง การจัดสรรหน่วยความจำแบบชัดเจน และการไม่มี control flow ที่ซ่อนอยู่
- Rust เคยเป็นทางเลือกเชิงปฏิบัติในการหลีกหนีจากการเปลี่ยนแปลงบ่อยครั้งและ ecosystem ที่ยังไม่สุกงอมของ Zig แต่ก็เผยข้อจำกัดในจุดต่าง ๆ เช่น FFI, cross compile และการจัดสรรหน่วยความจำที่ซ่อนอยู่
- การตัดสินใจกลับมาใช้ Zig ไม่ได้มีเพียงเหตุผลทางเทคนิคเท่านั้น แต่ยังมาจากความเชื่อมั่นต่อโปรเจกต์ Rust ที่ลดลงเกี่ยวกับ governance และ นโยบายโค้ดที่สร้างโดย LLM
- Zig ในปี 2026 ยังไม่เสถียร และ Zig 0.17.0 มีแผนจะทำให้ระบบ build ใช้ร่วมกันไม่ได้ แต่ความรู้สึกของภาษายังไม่ต่างจากปี 2020 มากนัก และประสบการณ์จัดการแพ็กเกจก็ดีขึ้น
- Zig ไม่ได้ให้ความปลอดภัยของหน่วยความจำใน compile time แบบ Rust แต่เลือกสมดุลระหว่างความเรียบง่ายกับความปลอดภัยขณะรันไทม์ผ่านแนวคิด ReleaseSafe, การทดสอบ, fuzzing และ assertion
จุดเริ่มต้นที่ทำให้สนใจ Zig
- รู้จัก Zig ครั้งแรกในปี 2020 ตอนนั้นดูเป็นภาษาใหม่ขนาดเล็กที่มี การรันโค้ดตอน compile time และ abstraction ที่เรียบง่าย
- ตอนเรียน C รู้สึกชอบความรู้สึกที่ได้ควบคุมคอมพิวเตอร์โดยตรง แต่ abstraction ที่เก่าและเครื่องมือที่ไม่เพียงพอก็ทำให้ไม่สะดวก
- แม้จะใหม่และไม่เสถียร Zig ก็ให้คำมั่นว่าจะเป็น ภาษาทดแทน C และสิ่งที่ดึงดูดคือการได้เรียน “ภาษาถัดไป”
- Software Should Be Perfect ของ Andrew Kelley ช่วยสร้างมาตรฐานในการมองภาษาโปรแกรมมิงและซอฟต์แวร์
- การจัดสรรหน่วยความจำแบบชัดเจนที่ล้มเหลวได้
- ไม่มี control flow ที่ซ่อนอยู่
- การนำกลับมาใช้ซ้ำได้อย่างเป็นสากล
- เมื่อใช้ Zig สร้างภาษาโปรแกรมมิงของเล่น, เครื่องมือ literate programming และเว็บเซิร์ฟเวอร์ ก็รู้สึกว่าเป็นภาษาที่สะดวกกว่า C แต่มีปัจจัยเสี่ยงน้อยกว่า
เหตุผลที่ย้ายไป Rust
- โค้ด Zig พังบ่อย และในฐานะนักศึกษาไม่มีเวลามากพอที่จะคอยแก้โปรเจกต์ให้เข้ากับเวอร์ชันภาษาล่าสุดอยู่เสมอ
- ตอนนั้นยังไม่มี anyzig ทำให้จัดการ Zig หลายเวอร์ชันบนระบบเดียวได้ไม่ง่าย
- บางครั้งกลับมาแตะโปรเจกต์หลังผ่านไปไม่กี่เดือน ก็ต้องทำ refactor ครั้งใหญ่ที่ตัวเองยังไม่เข้าใจเพื่อให้กลับมาทำงานได้
- ecosystem ก็ยังเล็กมาก
- ในฐานะโปรแกรมเมอร์มือใหม่ ยังไม่มีความสามารถพอที่จะสร้างทุกอย่างที่ต้องใช้เอง
- ไลบรารีและตัวอย่างมีน้อย
- standard library เปลี่ยนแปลงตลอด
- เอกสารพื้นฐานก็ยังไม่เสถียร
- Rust เป็นภาษาที่เสถียรมาหลายปีแล้ว และมี ecosystem ที่แข็งแรง
- การเรียน Rust นั้นยาก แต่เมื่อคุ้นเคยแล้ว โค้ดทำงานได้อย่างเสถียร และความเสถียรนั้นสำคัญมาก
- Rust เป็นภาษาที่เร็วและ low-level พร้อมให้พลังในการสื่อความที่จำเป็น และยังช่วยลดต้นทุนจากความไม่เสถียรที่เคยเจอใน Zig
- Rust ช่วยสร้าง memory model ที่มีประโยชน์แม้เวลาต้องใช้ภาษาที่มีการตรวจสอบในตัวน้อยกว่า
- ในโค้ดที่ไม่มี panic สามารถเขียนโค้ดที่นำกลับมาใช้ซ้ำได้โดยไม่มี control flow ที่ซ่อนอยู่หรือ garbage collector
- อย่างไรก็ตาม Rust ก็มีด้านที่ซ่อนการจัดสรรหน่วยความจำ และทำให้การทำงานร่วมกับ C ยากขึ้น
ความไม่พอใจที่ทำให้กลับมามอง Zig
- Rust ไม่ใช่ภาษาที่สมบูรณ์แบบสำหรับการสร้างโปรแกรมที่นำกลับมาใช้ซ้ำได้ตามที่ต้องการ
- FFI ทำได้ยาก
- cross compile ยุ่งยาก
- การจัดสรรหน่วยความจำที่ซ่อนอยู่และถูกปฏิบัติเสมือนว่าไม่ล้มเหลวเป็นภาระ
- ผูกติดกับ LLVM จึงอาจใช้เวลานานมาก หรือเป็นไปไม่ได้ ที่จะรองรับแพลตฟอร์มได้มากเท่า C
- governance ก็ยังเป็นจุดที่ทำให้อึดอัด
- Rust Foundation มี foundation members ที่เป็นบริษัทยักษ์ใหญ่หลายราย
- มองว่าเมื่อบริษัทใหญ่ที่สุดในโลกมอบเงินหลายแสนดอลลาร์ต่อปี ก็อาจมีอิทธิพลต่อทิศทางการพัฒนา Rust ได้
- การที่โปรเจกต์จำนวนมากในชุมชน open source เริ่มยอมรับโค้ดที่สร้างโดย LLM กลายเป็นเรื่องที่น่าตกใจ
- ในหลายโปรเจกต์ maintainer และผู้ใช้เริ่มเขียนหรือเรียกร้องนโยบายเกี่ยวกับ LLM
- Zig ห้ามใช้ LLM อย่างสิ้นเชิง ในโปรเจกต์
- Rust ทำแบบสำรวจ และความรู้สึกโดยรวมของชุมชนเป็นฝั่งต่อต้าน LLM แต่ก็ไม่ได้จัดทำนโยบายอย่างเป็นทางการทันที
- ข้อเสนอนโยบาย ของ Rust มีข้อกำหนดที่ห้ามกล่าวถึงหัวข้อต่อไปนี้ในคอมเมนต์ PR
- ผลกระทบระยะยาวทางสังคมและเศรษฐกิจของ LLM
- ผลกระทบด้านสิ่งแวดล้อมของ LLM
- สถานะลิขสิทธิ์ของผลลัพธ์จาก LLM
- การตัดสินทางศีลธรรมต่อผู้ใช้ LLM
- ข้อกำหนดนั้นถูกนำออกหลังถูกคัดค้าน แต่แค่ข้อเท็จจริงที่เคยมีข้อกำหนดแบบนั้นก็ทำให้ความเชื่อมั่นต่อโปรเจกต์ Rust ลดลง
- มองว่านโยบายโดยตัวมันเองส่วนใหญ่ถือว่าโอเค เพราะเป็นการจำกัด LLM และลด slop
- ประสบการณ์นี้กลายเป็นจุดเริ่มต้นให้กลับมาพิจารณา Zig อย่างจริงจังอีกครั้งหลังผ่านไปหลายปี
Zig ในปี 2026
- Zig ยังคง ไม่เสถียร
- พยายามเริ่มจากตัวอย่าง Zig 0.16.0 ที่เจอบนเว็บ แต่ตัวอย่างนั้นล้าสมัยไปแล้ว
- หากต้องการทำงานกับ Zig อย่างมี productivity วิธีที่ดีที่สุดคือเก็บสำเนาซอร์สของ standard library ไว้ใกล้ตัวและทำความคุ้นเคยกับมัน
- Zig 0.17.0 มีกำหนดจะปล่อยในเร็ว ๆ นี้ และจะทำให้ระบบ build ของทุกโปรเจกต์พัง
- maintainer กำลังพยายามมุ่งไปสู่ความเสถียร และการพังแบบนี้เป็นส่วนหนึ่งของกระบวนการนั้น
- โชคดีที่ตัวภาษาเองไม่ได้เปลี่ยนไปมากนักตั้งแต่ปี 2020
- สัญชาตญาณส่วนใหญ่ยังใช้ได้อยู่
- บางส่วนของไลบรารีถูกปรับทำใหม่ แต่โค้ดยังอ่านง่าย
- มองว่าโค้ด Zig ปัจจุบันก็น่าจะยังอ่านออกในอีก 6 ปีข้างหน้า
- ตอนนี้ Zig มี package manager แล้ว
- จำได้ว่าเมื่อก่อนใช้ git submodule ในการจัดการ dependency
- เครื่องมือในตัวดีกว่ามาก
- โปรเจกต์สามารถกำหนด dependency ผ่าน git และ tarball ได้
- vendoring ทำงานได้ง่าย
- ecosystem ยังไม่ใหญ่โต แต่สิ่งที่ Zig มุ่งหวังก็ไม่ใช่ ecosystem ขนาดมหึมา
- ไม่มี package registry อย่างเป็นทางการ และมีจุดยืนว่าไม่จำเป็นต้องมี NPM หรือ crates.io อีกอัน
- ประเมินว่า Zig ปัจจุบันสร้างสมดุลได้เหมาะสม
วิธีมองเรื่อง memory safety
- Zig ไม่ได้ให้ การรับประกัน memory safety แบบเดียวกับ Rust
- นี่เป็น trade-off เพื่อความเรียบง่าย และมองว่าความซับซ้อนของ affine type ใน Rust ไม่ได้คุ้มค่ากับประโยชน์ด้านความปลอดภัยเสมอไป
- แต่นั่นไม่ได้หมายความว่า Zig ละทิ้งความปลอดภัย
- จากมุมมองใน Zig is safer than unsafe Rust Zig อาจเป็นตัวเลือกที่ดีกว่าในสถานการณ์ที่ต้องใช้ unsafe Rust
- Zig ก็กำลังมีงานเพื่อทำให้ภาษาปลอดภัยขึ้นด้วย
- แนวทางไม่ได้โฟกัสที่เขตของ unsafe code แต่โฟกัสที่ release mode
- ปัจจุบันโหมด ReleaseSafe ของ Zig จะ crash เมื่อ assertion ล้มเหลว และจะ initialize หน่วยความจำทั้งหมด
- Andrew Kelley สนใจแนวทางที่จะรวมสิ่งคล้าย Fil-C เข้าไว้ใน ReleaseSafe
- วิธีนี้ไม่ได้ให้ memory safety ตอน compile time แบบ Rust ที่หลีกเลี่ยง
unsafeแต่ก็ไม่ได้มองว่าเป็น death spiral อย่างที่บางคนพูด - memory safety เป็นสเปกตรัม และไม่มีแนวทางเดียวที่ดีที่สุดสำหรับทุกสถานการณ์
- แนวทางของ Zig คือทำให้ ReleaseSafe ปลอดภัยที่สุดเท่าที่ทำได้ใน runtime และตรวจสอบความถูกต้องด้วยการทดสอบและ fuzzing
- illegal behavior ที่ไม่ได้ตรวจสอบต้องถูกค้นพบในกระบวนการนี้ และเมื่อพิสูจน์ความถูกต้องแล้ว ก็มองว่าสามารถเผยแพร่ไบนารีใน release mode อื่นได้อย่างปลอดภัย
- วิธีนี้มีข้อเสียเมื่อเทียบกับโมเดลของ Rust แต่เมื่ออยู่ในทิศทางของ Zig ที่ให้ความสำคัญกับความเรียบง่ายอย่างมาก ก็ไม่ได้มองว่าด้อยกว่าโดยสิ้นเชิง
- หาก memory safety ตอน compile time สำคัญพอที่จะยอมรับต้นทุนของ type system ที่ซับซ้อนและเวลา compile ที่ยาวนาน ก็ควรเลือก Rust
- โมเดล memory safety ของ Zig ยังต่อเนื่องไปถึงปรัชญา assertion ด้วย
- แทนที่จะปิด assertion ใน ReleaseFast ก็เชื่อว่าการทดสอบได้พิสูจน์แล้วว่า assertion นั้นถูกต้อง และ path นั้น unreachable
- สิ่งนี้ทำให้ Zig optimize โค้ดได้
- บทความที่เกี่ยวข้องคือ your assertions are correct
แนวทางการใช้งานต่อจากนี้
- พร้อมที่จะใช้ Zig จัดการปัญหาซอฟต์แวร์ โดยมี standard library และบันทึกการเปลี่ยนแปลงของ release อยู่ข้างตัว
- เมื่อต้องการหลีกเลี่ยงรายละเอียด low-level จะใช้ ภาษา scripting ที่ชอบ
- ในซอฟต์แวร์ต่อจากนี้ วางแผนให้ Zig เป็นเครื่องมือหลัก
- ยังเปิดความเป็นไปได้ว่าจะไม่ได้อยู่กับ Zig ตลอดไป
- หากต้องการความเสถียรหรือ type system ของ Rust ก็สามารถใช้ Rust ได้
- ความคิดเกี่ยวกับแนวทางของ Zig อาจเปลี่ยนไปโดยสิ้นเชิงก็ได้
- หลายภาษาสามารถและควรอยู่ร่วมกันได้
- Zig เป็นตัวแทนของวิสัยทัศน์ซอฟต์แวร์ที่โฟกัสผู้ใช้ ด้วยการยอมรับคุณภาพของซอฟต์แวร์แทนที่จะละเลยมัน
- ผู้คนสมควรได้รับซอฟต์แวร์ที่เชื่อถือได้และทรงพลัง และมองว่าใน ยุค LLM ซอฟต์แวร์ที่สร้างอย่างประณีตกำลังหายากขึ้น ขณะที่ผู้คนถูกกดดันให้ยอมรับ slop ที่แย่ลงเรื่อย ๆ
3 ความคิดเห็น
ผมเคยมีประสบการณ์ที่ระหว่างกำลังเรียน Zig อยู่ เห็นข่าวว่าจะมีเวอร์ชันใหม่ออกมา เลยเลิกเรียนไปครับ
ถ้ามีเวอร์ชันที่เสถียรออกมา ก็น่าจะลองเอากลับเข้าไปไว้ในรายการที่อยากเรียนอีกครั้งได้ แต่จนถึงตอนนี้ breaking changes ยังเยอะเกินไป เลยกลัวที่จะไปแตะครับ
ขณะที่ Zig เปลี่ยนสเปกของภาษา ก็มักจะทิ้งความเข้ากันได้ย้อนหลังอยู่เรื่อย ๆ แบบนี้ผมคิดว่าอย่างน้อยจนกว่าจะออก 1.0 ก็คงลำบากที่จะใช้ในระบบสำคัญ ๆ
ดูเหมือนว่า ghostty จะเจอปัญหาหนักพอสมควรเพราะการเปลี่ยนแปลงของ std.IO ประเด็น
ถ้ายกตัวอย่างจากภาษาอื่น สมมติว่าใน Java หลังจากมี
Futureแล้ว JDBC API เปลี่ยนไปคืนค่าเป็น Future หรือ CompletableFuture ก็คงมีความก้าวหน้าอย่างมากแน่นอน แต่แลกมาด้วยความสับสนวุ่นวายมหาศาลเช่นกันความคิดเห็นจาก Lobste.rs
สักวันหนึ่งอยากลองใช้ Zig อีกครั้ง
อยากลองจริง ๆ แต่จนถึงตอนนี้ยุ่งกับงานอื่นมาตลอด
ครั้งสุดท้ายที่แตะ Zig ผมเจอ ข้อผิดพลาดของคอมไพเลอร์ ภายในประมาณ 3 ชั่วโมง และมันค่อนข้างติดตาเลย พูดอย่างเป็นธรรม บั๊กนั้นถูกแก้แล้วในบรานช์ล่าสุด
รู้สึกสงสัยกับคำพูดที่ว่า “เพราะผูกติดกับ LLVM จึงอาจใช้เวลานานมาก หรืออาจไม่มีวันรองรับแพลตฟอร์มได้มากเท่า C”
อยากรู้ว่าหมายถึงต้องการพัฒนาเพื่อ แพลตฟอร์มใดที่ LLVM ไม่รองรับ และในแง่นี้ Zig ดีกว่าอย่างไร
อยากถามว่าหมายถึง Zig สร้างโค้ด C ระดับ tier-4 แล้วให้ GCC คอมไพล์สำหรับ hppa, alpha, sh ได้ใช่ไหม
ปัญหาคือ Zig มีแบ็กเอนด์ทางการนอกเหนือจาก LLVM แต่ Rust ใช้ LLVM
ถ้าเป็นภาษาเชิงระบบที่มุ่งเพิ่มการนำซอฟต์แวร์กลับมาใช้ซ้ำให้ได้มากที่สุด ก็ควรรันได้กว้างที่สุดเท่าที่เป็นไปได้ และยิ่งเป็นเช่นนั้นหากตั้งใจจะมาแทน C แบบ Zig
เห็นความสำเร็จของ ghostty แล้ว หาก Zig ไปถึง 1.0 ก็วางแผนจะลองใช้กับ การพัฒนาเกม
แต่ก็ไม่ค่อยแน่ใจว่าเกมประเภทที่ผมทำต้องการประสิทธิภาพระดับนั้นจริงหรือไม่
คำพูดทำนองว่า “Zig ไม่ได้ละทิ้งความปลอดภัย และปลอดภัยกว่า unsafe Rust ถ้าอยู่ในสถานการณ์ที่ต้องใช้ unsafe Rust อยู่แล้ว Zig อาจดีกว่า” พบได้ค่อนข้างบ่อย แต่ทุกครั้งที่เห็นก็ไม่ค่อยเข้าใจ
โดยเฉพาะเมื่อผู้เขียนยอมรับว่า ความปลอดภัยเป็นสเปกตรัม แต่กลับแนะนำให้เปลี่ยนไปใช้ภาษาที่ทุกอย่างยังคง unsafe แทนการใช้พื้นที่ unsafe เฉพาะจุด ซึ่งดูแปลก
เครื่องจักรเชิงนามธรรมอาจให้เหตุผลได้ง่ายขึ้นเล็กน้อย แต่การแลกเปลี่ยนแบบนั้นยังไม่น่าเชื่อถือสำหรับผม