- ฟีเจอร์ comptime ของ Zig มอบ ความสามารถในการประเมินผลขณะคอมไพล์ที่ทรงพลังมาก แต่ก็ ถูกจำกัดไว้โดยเจตนา
- เมื่อรันโค้ดในช่วงคอมไพล์ จะ ไม่สามารถเข้าถึงข้อมูลของโฮสต์ได้ ซึ่งเป็นการออกแบบที่เหมาะกับการครอสคอมไพล์
- ไม่รองรับการสร้างโค้ดแบบไดนามิก, DSL, RTTI, I/O เป็นต้น แต่ใช้การทำโค้ดให้เฉพาะทางตามชนิดแบบชัดเจนแทน
- RTTI สามารถทำขึ้นเองได้ โดยสามารถประกอบข้อมูลชนิดที่มีอยู่เฉพาะตอนคอมไพล์ใหม่ให้ใช้งานได้ในรันไทม์
- สามารถสร้างชนิดใหม่ด้วย comptime ได้ แต่ขยาย API ไม่ได้ ไม่สามารถเพิ่มเมธอดที่ผู้ใช้กำหนดเองได้
สิ่งที่ comptime ของ Zig ไม่ได้ทำ
- แม้
comptime ของ Zig จะมอบความสามารถทรงพลังอย่าง generics, conditional compilation, serialization, ORM และอื่น ๆ แต่ บางความสามารถก็ถูกจำกัดไว้อย่างชัดเจน
- ข้อจำกัดเหล่านี้กลับทำให้การออกแบบของ Zig กระชับและคาดเดาได้มากขึ้น
-
เข้าถึงข้อมูลโฮสต์ไม่ได้ (No Host Leakage)
- โค้ด
comptime จะ ทำงานโดยยึดตามแพลตฟอร์มเป้าหมาย ไม่ใช่ระบบที่ใช้รันโค้ดนั้น
- ใน Zig ระหว่างคอมไพล์ ไม่สามารถใช้ข้อมูลอย่าง endian ของระบบโฮสต์, ขนาดพอยน์เตอร์ ฯลฯ ได้
- จุดประสงค์คือเพื่อ รับประกันความปลอดภัยสำหรับการครอสคอมไพล์
- ในโค้ดตัวอย่าง ผลลัพธ์ไบต์ของตัวเลขรูปแบบ BF16 จะแตกต่างกันตามแพลตฟอร์มเป้าหมาย
-
ไม่มีการสร้างโค้ดจากสตริง (No #eval)
- Zig ไม่ได้มีความสามารถในการ สร้างโค้ดแบบไดนามิก เหมือน
#include ของ C, mixin ของภาษา D หรือ macro ของ Rust
- แต่รองรับ partial evaluation ที่อิงกับอาร์กิวเมนต์
comptime
- หากอาร์กิวเมนต์บางตัวทราบได้ตั้งแต่ตอนคอมไพล์ ก็จะเหลือเฉพาะสาขานั้นไว้ ทำให้ ปรับแต่งโค้ดให้เหมาะสมได้
-
ขยายไวยากรณ์ DSL ไม่ได้ (No DSLs)
- ใน Zig ไม่มีความสามารถในการ สร้างไวยากรณ์ (syntax) ที่ผู้ใช้กำหนดเอง แบบ Lisp หรือ Rust
- ข้อมูลทั้งหมดจะถูกส่งผ่านในรูปของ ค่า (value) ตามไวยากรณ์ของ Zig เท่านั้น
- DSL แบบจำกัดอย่างฟอร์แมตสตริง (
printf) สามารถทำได้ ผ่านสตริง comptime เท่านั้น
-
ไม่มีข้อมูลชนิดในรันไทม์ (No RTTI)
- Zig อาจทำงานได้คล้ายภาษาไดนามิกอย่าง Python แต่ ข้อมูลชนิดจะมีอยู่เฉพาะใน
comptime เท่านั้น
- หากต้องการให้ใช้ได้ในรันไทม์ ต้อง นิยามโครงสร้าง RTTI เองและจัดการผ่านพอยน์เตอร์
- ตัวอย่าง: นิยามโครงสร้าง
RTTI ที่เก็บชื่อฟิลด์และข้อมูล offset ของ struct แล้วเข้าถึงฟิลด์ผ่านพอยน์เตอร์
-
สร้าง API ใหม่ไม่ได้ (No New API)
- ใน Zig แม้จะสร้างชนิดใหม่ด้วย
comptime ได้ แต่ ไม่สามารถเพิ่มเมธอดให้ชนิดนั้นได้
- จึงไม่สามารถขยาย API ได้เหมือน derive macro ของ Rust
- เมื่อต้องทำ JSON serialization จะไม่สามารถเพิ่มเมธอด
.to_json() ได้ และต้อง ทำผ่านการส่ง type argument ให้ฟังก์ชันส่วนกลางแทน
-
ไม่มี IO ขณะคอมไพล์ (No IO)
comptime ของ Zig ห้ามเข้าถึงทรัพยากรภายนอก เช่น file system, network, database
- ผลคือ มีความสามารถในการทำซ้ำได้สูงขึ้น ปลอดภัยขึ้น และใช้แคชได้ดีขึ้น
- หากต้องใช้ IO ให้ใช้ระบบ build อย่าง
build.zig เพื่อ สร้างโค้ด Zig ล่วงหน้าแล้ว import เข้ามา
-
สรุป: El Disco (สมดุลระหว่างนามธรรมกับความเรียบง่าย)
- Zig มอบความสามารถด้าน metaprogramming ที่ทรงพลัง แต่ก็รักษาความคาดเดาได้ผ่านการออกแบบที่จำกัดอย่างมาก
- ด้วยข้อจำกัดเหล่านี้
comptime ของ Zig จึง ยังคงมีความเป็นภาคปฏิบัติและเข้าใจได้ง่าย
- แม้ไม่มีนามธรรมที่ซับซ้อน ก็ยังมีประโยชน์ต่อการใช้งานจริง และ ทำงานได้ชัดเจนตามความสามารถที่ประกาศไว้เท่านั้น
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
comptimeของ Zig มีคุณลักษณะที่โดดเด่นข้อเสียและแนวทางแก้ของ
comptimeใน Zigzig buildแล้วคอมไพล์ด้วยการ@importวลีภาษาสเปนที่อ้างจากเรื่องสั้นของ Borges เกี่ยวข้องกับเทพเจ้านอร์ส
ความยืดหยุ่นของ
comptimeจุดเด่นที่ทำให้
comptimeของ Zig เป็นที่รู้จักบล็อกโพสต์ที่ให้ความรู้
comptime forและinline forinlineจะรู้ความยาวได้เฉพาะในcomptimeเท่านั้นความเห็นเชิงบวกต่อภาษาและเครื่องมือของ Zig
ประเด็นที่น่าสนใจเกี่ยวกับ
comptimeของ Zigความสับสนเกี่ยวกับการรันโค้ดในช่วงคอมไพล์