- ใน Zig เวอร์ชัน 0.15 ได้มีการนำ อินเทอร์เฟซ IO ใหม่ (std.Io.Reader, std.Io.Writer) เข้ามาใช้
- มีเป้าหมายเพื่อปรับปรุงความซับซ้อนของวิธี IO แบบเดิมและปัญหาด้านประสิทธิภาพ แต่กลับเกิด ความสับสนในการใช้งานจริง
- การใช้ tls.Client และ buffer มีรูปแบบการส่งพารามิเตอร์ที่ไม่สอดคล้องกัน จึงยิ่งเพิ่มความสับสน
- แม้แต่การทำตัวอย่างการใช้งานพื้นฐานก็ยังมีข้อกำหนดที่ซับซ้อน เช่น การระบุ ขนาดบัฟเฟอร์หลายแบบและฟิลด์ออปชัน
- เอกสารทางการ ตัวอย่างโค้ด และฟังก์ชันอำนวยความสะดวกยังมีไม่เพียงพอ ทำให้ ไม่เป็นธรรมชาติสำหรับผู้เริ่มต้น
อินเทอร์เฟซ IO ใหม่ที่นำมาใช้ใน Zig 0.15 และที่มา
- ใน Zig เวอร์ชัน 0.15 ได้มีการนำประเภท IO ใหม่คือ std.Io.Reader และ std.Io.Writer เข้ามาใช้
- อินเทอร์เฟซ IO แบบก่อนหน้าก่อให้เกิดความซับซ้อนจากปัญหาด้านประสิทธิภาพ การปะปนของประเภท และการใช้
anytype มากเกินไป
- เป้าหมายหลักของโครงสร้าง IO ใหม่คือการแยกประเภทระหว่างอินเทอร์เฟซให้ชัดเจนและปรับปรุงประสิทธิภาพ
ปัญหาจริงในการใช้ tls.Client และอินเทอร์เฟซ IO
- ระหว่างการอัปเดตไลบรารี smtp เดิม ได้เกิดความสับสนกับวิธีใช้ฟังก์ชัน tls.Client.init
- ตามเอกสาร ฟังก์ชัน init ระบุว่าต้องรับ พอยน์เตอร์ของ Reader และ Writer พร้อมชุดออปชัน เป็นอาร์กิวเมนต์
- net.Stream ของ Zig จะคืนค่า Stream.Reader/Writer ผ่านเมธอด reader() และ writer() ตามลำดับ
- แต่ Stream.Reader/Writer กับ std.Io.Reader/Writer ไม่ใช่ประเภทเดียวกันแบบตรงตัว จึงต้องมีการแปลง
- ฝั่ง Reader ต้องเรียกเมธอด interface() ส่วน Writer ต้องใช้ฟิลด์ &interface จึงดูขาดความสอดคล้อง
ปัญหาเรื่องการตั้งค่าบัฟเฟอร์และฟิลด์ออปชัน
stream.writer, stream.reader ต่างก็รับบัฟเฟอร์เป็นอาร์กิวเมนต์
- Buffer ถูกเน้นว่าเป็นองค์ประกอบจำเป็นในอินเทอร์เฟซ IO ใหม่นี้
- เมื่อเรียก
tls.Client.init จำเป็นต้องมี ฟิลด์ออปชัน 4 รายการ ได้แก่ ca_bundle, host, write_buffer, read_buffer
- กฎในการแยกค่าว่าบางส่วนส่งผ่านพารามิเตอร์ออปชัน และบางส่วนส่งเป็นอาร์กิวเมนต์โดยตรง ให้ความรู้สึกว่าไม่ชัดเจน
var tls_client = try std.crypto.tls.Client.init(
reader.interface(),
&writer.interface,
.{
.ca = .{.bundle = bundle},
.host = .{ .explicit = "www.openmymind.net" } ,
.read_buffer = &read_buf2,
.write_buffer = &write_buf2,
},
)
- ในทางปฏิบัติ หากไม่ได้ส่งพอยน์เตอร์ของบัฟเฟอร์อย่างถูกต้อง โปรแกรมอาจทำงานผิดปกติ หรือเกิดอาการค้างและล่มได้หลากหลายรูปแบบ
ปัญหาด้านความเป็นธรรมชาติเมื่อใช้ Reader
- แม้ฟิลด์ reader ของ
tls.Client เองจะเป็น "สตรีมที่ถอดรหัสแล้ว" แต่ใน std.Io.Reader กลับไม่มีเมธอด read แบบทั่วไป
- กลับมีเพียงเมธอดที่เข้าใจได้ยากกว่า เช่น
peek, takeByteSigned, readSliceShort
- API ที่พอใกล้เคียงกับการใช้งานทั่วไปมากที่สุดคือการอ่านข้อมูลเข้าไปยังบัฟเฟอร์ผ่านเมธอด stream
var buf: [1024]u8 = undefined;
var w: std.Io.Writer = .fixed(&buf);
const n = try tls_client.reader.stream(&w, .limited(buf.len));
ตัวอย่างโค้ดทั้งหมดและปัญหาในการใช้งานจริง
- ต่อให้พยายามทำตัวอย่างขั้นต่ำสุดที่ทำงานได้จริง ก็ยังมีหลายจุดที่ต้องใส่ใจ เช่น ออปชัน ขนาดบัฟเฟอร์ และการแปลงประเภท
- การขาดแคลนการทดสอบ เอกสาร และตัวอย่าง ทำให้ความยากในการเรียนรู้และกำแพงในการเริ่มต้นสูงขึ้น
- หากยังไม่เข้าใจเรื่องความสอดคล้องภายในภาษา Zig หรือแนวคิดเบื้องหลังการออกแบบ ก็มีหลายจุดที่ให้ความรู้สึกแปลก
- แม้แต่ใน standard library เอง แนวทางนี้ก็ยังไม่ได้ถูกใช้อย่างแพร่หลาย จึงมีข้อมูลอ้างอิงสำหรับงานจริงค่อนข้างน้อย
ประสบการณ์และข้อสรุป
- การเปลี่ยนชื่ออย่าง
std.fmt.printInt รวมถึงการเปลี่ยนแปลงด้านการออกแบบ API ทำให้กระบวนการ migration ไม่ใช่เรื่องง่าย
- ได้พบความยากซ้ำ ๆ หลายจุด เช่น รูปแบบ
reader.interface(), &writer.interface, วิธีส่งออปชัน และความจำเป็นต้องใช้บัฟเฟอร์หลายชุด
- สำหรับผู้ที่ไม่คุ้นเคยกับโปรโตคอลเครือข่ายหรือความปลอดภัยอย่าง TLS การทำความเข้าใจข้อกำหนดยิ่งรู้สึกยากขึ้นไปอีก
- โดยสรุปแล้ว เมื่อเทียบกับเดิม ยังมีหลายส่วนที่ ขาดความชัดเจน การจัดทำเอกสาร และความสะดวกในการใช้งาน
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ขอแจ้งว่าเป็นผู้เขียนเอง ในที่สุดก็ทำให้มันทำงานได้ถูกต้อง ทั้ง
writerแบบเข้ารหัสและstream writerต่างก็ต้องมีขั้นตอนflushและในฝั่งอ่านก็มีปัญหาอยู่ด้วย สตรีมมิงนั้นทำงานได้ แต่เพราะWriter.Fixedไม่ได้ implementsendFileการอ่านครั้งแรกจึงคืนค่า 0 เสมอ หลังจากเรียกครั้งแรก ภายในจะสลับจากโหมดสตรีมมิงไปเป็นโหมดอ่าน ทำให้จู่ ๆ ทุกอย่างก็เริ่มทำงานได้หมด (ลิงก์โค้ดที่เกี่ยวข้อง: Zig File.zig #L1318) ตอนนี้กำลังพยายามเปิดฟีเจอร์บีบอัดกลับเข้าไปในไลบรารี websocketทำให้นึกถึงมีม YouTube ว่า "อย่าลืม
flush" (วิดีโอ YouTube)ชักสงสัยว่า principle of least surprise หายไปอยู่ไหน
รู้สึกทึ่งมากที่ย้ายจากอินเทอร์เฟซก่อนหน้ามาเป็นสภาพแบบตอนนี้ได้ น่าประหลาดใจสุด ๆ
ไม่ได้เป็น PM ของ Zig แต่ทางออกแรกที่ชัดเจนที่สุดสำหรับปัญหาที่ OP เจอ ก็คือทำเอกสารให้ดีกว่านี้และเพิ่มตัวอย่างการใช้งานให้มากขึ้น (จะเยอะแค่ไหนก็ไม่เป็นไร) การทำแบบนั้นอาจเป็นโอกาสดีในการทบทวนด้วยว่ากำลังให้ผู้ใช้ต้องทำอะไรเยอะเกินไปหรือเปล่า ถ้าเป้าหมายคือประสิทธิภาพสูงสุดแบบถึงที่สุด หรือหลีกเลี่ยงการใส่ abstraction ที่ทำให้ performance ลดลง ก็ดูเหมือนจะทำสำเร็จแล้ว แต่ DX นั้นเหมือนหลุดไปถึงกาแล็กซีแอนดรอเมดา
ดูเหมือนคุณจะยังไม่ค่อยรู้จักวัฒนธรรมของคอมมูนิตี้ Zig ถ้าบ่นว่าเอกสารไม่พอ ทุกคนก็พร้อมจะเข้ามาคอมเมนต์ว่า "ไปอ่านโค้ด stdlib เองสิ" API ส่วนใหญ่ใช้งานยากแบบที่บทความนี้เล่า และแม้แต่งานพื้นฐานอย่าง HTTP หรือไฟล์ซิสเต็ม ถ้าไม่คุ้นก็ลำบากมาก เพราะงั้นจึงเหมือนเหลือรอดเฉพาะคนที่เก่งจริง ๆ
การเขียนเอกสารมีต้นทุนและใช้เวลา เวลานั้นเอาไปพัฒนาส่วนอื่นของ Zig ก็ได้ ถ้าเป็นโค้ดที่ยังทำอยู่ การเลื่อนเอกสารออกไปจนกว่าจะนิ่งสนิทก็เป็นทางเลือกที่สมเหตุสมผล แน่นอนว่าเอกสารเป็นเรื่องดี แต่ถ้าต้องจัดลำดับความสำคัญระหว่างฟีเจอร์ใหม่ การแก้บั๊กสำคัญ หรือการทำเอกสาร ก็ไม่ได้มีครบทุกอย่างเสมอไป
ดูเหมือน zig จะโฟกัสกับการบอกว่าห้ามทำอะไร มากเกินไป อยากให้มันพัฒนาไปทางการรวบรวมหลายวิธีและตัวอย่างการใช้งาน แล้วจัดระเบียบและสื่อสารให้ดีมากกว่า กรณีเอกสารของอินเทอร์เฟซนี้ที่ขาดหายไปก็คือตัวอย่างชัด ๆ
การเขียนเอกสารหรือทำตัวอย่างที่ดีต้องใช้แรงมาก พอเห็นขอบเขตของการเปลี่ยนแปลงที่กำลังเกิดขึ้นใน zig ตอนนี้ ต่อให้ทำเอกสารไปก่อนที่จะลงตัวจริง ไม่นานก็อาจใช้ไม่ได้แล้ว
ฉันไม่ใช่นักพัฒนา Zig แต่คิดว่าเหตุผลหนึ่งที่เอกสารของ Zig กระชับมากเกินไป คือภาษายังใหม่และยังพัฒนาเปลี่ยนแปลงอยู่ตลอด จึงเข้าใจได้ว่ามันยากจะทุ่มเวลาและพลังไปกับการเขียนเอกสาร ทั้งที่รู้อยู่แล้วว่าอีกไม่นานอาจไม่ถูกต้องแล้ว
ตัวภาษา Zig เองดีมากจริง ๆ แต่ standard library ยังไม่เสร็จอีกเยอะ เปลี่ยนตลอด ขาดอีกมาก และบางส่วนก็ abstraction เยอะเกินไป ขณะที่บางส่วนก็ low-level เกินไป ตอนนี้ผมคิดว่าใช้ OS API ตรง ๆ ยังดีกว่าใช้ standard library ถ้าไม่ได้ตั้งใจเป็นเบต้าเทสเตอร์ ก็แนะนำให้เลี่ยง standard library ไปก่อน
จริง ๆ เวลาผมใช้ zig ก็มักจะเน้น OS API เหมือนกัน
cImportsทำมาได้ดี เลยหยิบมาใช้ได้ง่ายเวลาขี้เกียจเขียนนิยามของ zig เองในมุมมองผม Zig พยายามทำหลายอย่างเกินไปพร้อมกัน จนไปไม่ถึงแม้แต่เส้นคุณภาพขั้นต่ำที่ผมคิดไว้ มันดูเหมือนบีบให้ผู้ใช้ต้องยอมรับการเปลี่ยนแปลงรุนแรงและการทดลองต่าง ๆ จนต้องมีคนจำนวนมากพอคอยลงทุนกับภาพฝันว่า "ก่อน 1.0 จะพังยังไงก็ได้ สักวันมันจะดีขึ้นเอง" (ซึ่งผมสรุปว่า วันนั้นคงไม่มาถึง) ผมไม่คิดว่าการผลักภาระการทดลองของตัวเองให้คนอื่นเป็นเรื่องดี ต่อให้เตือนไว้ล่วงหน้าว่ายังไม่เสถียร หรือบอกว่าอย่าพึ่งพามัน คนที่เจอ rug pull อยู่ดี ก็ยังเดือดร้อนอยู่ดี ผมไม่แน่ใจว่า zig คืออะไรกันแน่ Matklad เรียกมันว่า machine level language (บทสัมภาษณ์ที่เกี่ยวข้อง: lobste.rs - สัมภาษณ์ Matklad) แต่หน้าเว็บทางการบอกว่าเป็นภาษา general-purpose ที่ robust, optimal, reusable ซึ่งสองอย่างนี้ขัดกันเอง และยังมีปัญหาจำนวนมากที่ไม่จำเป็นต้องจัดการหน่วยความจำเอง ดังนั้น zig จึงไม่ใช่ภาษาอเนกประสงค์จริง ๆ ความสับสนทั้งหมดนี้สะท้อนออกมาในความไม่เสถียรของ zig และ standard library ที่ใหญ่เทอะทะ การอ้างว่าทั้งเรียบง่ายและอเนกประสงค์ แต่มีไลบรารีใหญ่ขนาดนี้เป็นเรื่องย้อนแย้ง Async ก็เหมือนถูกสัญญาว่าเป็นคำตอบสารพัด ทั้งที่มันไม่ใช่ความสามารถที่ทำได้อย่างมีประสิทธิภาพแบบทั่วไปในทุกแพลตฟอร์ม สมัยก่อนยังโปรโมตว่ามันแก้ปัญหา function coloring ได้ แต่ความพยายามนั้นก็ถูกทิ้งไปแล้ว ตรรกะที่ให้เชื่ออีกครั้งว่าคราวนี้จะทำได้จริงดูแปลกมาก ที่จริงแล้วถ้าต้องการแค่คอมไพเลอร์ที่ทำงานได้ทุกแพลตฟอร์ม ก็แค่มีชุดคำสั่งแอสเซมบลีพื้นฐานที่ใช้สร้างคอมไพเลอร์ได้ก็พอ
luajitถึงขั้นเขียน parser เป็นแอสเซมบลีล้วนและยังทำงานได้ดีทุกที่ ผมเขียนโปรแกรมส่วนใหญ่ด้วย lua และแทบไม่เคยเจอบั๊กในอินเทอร์พรีเตอร์เลย นึกไม่ออกด้วยว่า zig จะแก้ปัญหาอะไรได้ดีกว่า luajit แม้จะมีบางอย่างที่ต้องใช้ zig จริง ๆ ก็ embed ส่วนนั้นเข้าไปในโค้ด lua แล้วต่อผ่าน FFI ได้ โค้ดส่วนใหญ่ไม่ได้ต้องการการปรับแต่ง low-level ขนาดนั้นจริง ๆ การเอา zig เข้ามากลับทำให้ปวดหัวกว่าเดิม ทุกวันนี้ความคาดหวังเกินจริงต่อ zig ชวนให้นึกถึงช่องว่างระหว่าง AI กับความเป็นจริง ถ้าจะเชื่อ zig ก็ต้องเชื่อความหวังลม ๆ แล้ง ๆ ว่ามันจะมีความสามารถที่ตอนนี้ยังไม่มีในสักวัน ทั้งที่ไม่มีแผนปฏิบัติการชัดเจน มีแต่แนวว่า "รออีกหน่อยสิ"ผมไม่เข้าใจว่าทำไมไลบรารีหรืออินเทอร์เฟซต้องการให้ผมจัดสรรบัฟเฟอร์ของไทป์นั้นเอง ถ้าผมต้อง parse เองอยู่แล้ว ก็ไม่ต้องมีไลบรารีก็ได้ และถ้าใช้จริง มันก็อาจทำให้การแลกเปลี่ยนพังได้ อินเทอร์เฟซแปลก ๆ ของ go มีอยู่เพราะบางอินเทอร์เฟซขยาย
writerinterface ออกไป (ดูhijackerinterface) หรือเพราะrequestobject ถูกนำกลับมาใช้ใหม่ได้หลายแบบในหลาย middleware สรุปคือrequestไม่จำเป็นต้องขยายได้ แต่responseสามารถเปลี่ยนรูปได้หลายแบบ เช่น websocket หรือ wrapper ของ TCPผมไม่ได้รู้สึกว่าไลบรารีที่ให้จัดสรรบัฟเฟอร์จากภายนอกเป็นเรื่องแปลก มันให้ความยืดหยุ่นมากขึ้น แลกกับงานทำมือที่มากขึ้น ตัวอย่างเช่น ถ้าคุณมี buffer pool ที่ทำไว้แล้ว คุณก็อาจอยากใช้ซ้ำ ถ้าไทป์นั้นจัดสรรเองภายใน ก็จะทำแบบนั้นไม่ได้ หรือในสภาพแวดล้อมที่ต้องจัดสรรทุกทรัพยากรไว้ล่วงหน้า ก็อาจไม่มีสิทธิ์จัดสรรทีหลังได้ ข้อเสียคือมีผู้ใช้แค่ 10% ที่ต้องการความยืดหยุ่นแบบนี้ แต่อีก 90% แค่จะจัดสรรบัฟเฟอร์แล้วส่งเข้าไป ทำให้ทุกคนต้องรับความซับซ้อนเพิ่ม วิธีที่ดีที่สุดคือน่าจะเปิดให้ยืดหยุ่นสูง แต่กรณีง่าย ๆ ก็ยังใช้ง่ายได้ เช่น ส่งบัฟเฟอร์ความยาว 0 (หรือ
nullของ Zig) เข้าไป แล้วให้ไทป์จัดสรรเอง และมี constructor แบบง่ายที่สร้างได้โดยไม่ต้องมีบัฟเฟอร์ด้วย แน่นอนว่าสิ่งเหล่านี้ก็เพิ่มภาระงานเอกสารเต็ม ๆมันคล้ายความต่างด้านธรรมเนียมที่แต่ละภาษาเลือกใช้ (ประมาณเรเดียน/องศา) IO แบบไหนก็แปลงกันได้อย่างอิสระ ฝั่งหนึ่งอาจเรียกมันว่า mock อีกภาษาหนึ่งอาจเรียกว่า
unsafeFooก็ได้ Andrew Kelley ไปค้นพบแพตเทิร์นที่คอมมูนิตี้ Haskell ถกกันมา 30 ปีด้วยตัวเองในไลฟ์สตรีม ดังนั้นอนาคตก็คือ Zig เขาเข้าใจก่อนคนอื่นความหมายของ external buffer ก็คือฟังก์ชันจะข้ามการจัดสรรบัฟเฟอร์ไป
ผมไม่มีแผนจะอัปเกรด side project ที่เขียนด้วย zig ไปเป็น 0.15.x เข้าใจนะว่าทำไม Andrew ถึงเลือกออกรีลีสและปล่อย Io ใหม่ให้กลุ่ม early adopter ได้ลอง แต่เพิ่งผ่านการเปลี่ยน readers/writers ครั้งใหญ่มาได้ไม่กี่วันเอง สำหรับคนทำงานกับ standard library นี่เป็นเรื่องดี แต่สำหรับคนที่ใช้ zig เป็นงานอดิเรกแบบผม ดูจะฉลาดกว่าถ้ารอถึง 0.16.0 หลังจากมันนิ่งแล้ว
ถ้าภาษาชื่อ Zig ก็อดนึกมุกไม่ได้ว่า บางทีก็ควร Zag บ้างเหมือนกัน
Loris Cro ซึ่งเป็นสมาชิกแกนหลักของ Zig ก็พูดในบทสัมภาษณ์ล่าสุดเหมือนกันว่าจะเลื่อนการอัปเดต zig ในโปรเจ็กต์ของตัวเองออกไปจนกว่าผลกระทบจากการเปลี่ยน IO จะสงบลง แต่เขายังมองภาพรวมในแง่บวก ทั้ง Andrew และ Loris ต่างก็เห็นว่านี่น่าจะเป็นการเปลี่ยนแปลงใหญ่ครั้งสุดท้าย จึงคาดหวังได้ว่า 1.0 คงอยู่ไม่ไกล ตัวแปรใหญ่ที่สุดตอนนี้มีแค่ผลกระทบจาก stack-less coroutine ที่กำลังจะถูกนำกลับมาใช้ใหม่
หลังจากอ่านโพสต์เรื่องอินเทอร์เฟซ IO ใหม่ ผมก็ตัดสินใจเลี่ยง zig ไปเลย รู้สึกว่าอย่างน้อยสัญชาตญาณของผมก็ถูก ถึงเหตุผลจะต่างกัน แต่สุดท้ายมันให้ความรู้สึกซับซ้อนไม่ต่างจากความยืดเยื้อก่อนยุค C++11 เหมือนกำลังเห็นแพตเทิร์นเดิม ๆ ที่ภาษาใหม่พยายามเข้ามาแทนที่ของเก่า แต่สุดท้ายก็ซับซ้อนพอ ๆ กัน
ประเด็นที่ OP ชี้ว่า การแปลง
Stream.Readerเป็นstd.Io.Readerต้องเรียกเมธอดinterface()แต่ถ้าจะเอาstd.io.WriterจากStream.Writerกลับต้องใช้ address ของฟิลด์&interfaceนั้น ดูไม่สอดคล้องกัน ซึ่งผมคิดว่าถ้าเป็นคอมมูนิตี้ Go คงปัดตกไปตั้งแต่แรก Go มักตัดสินใจแม้เรื่องเล็กน้อยหลังผ่านการวิเคราะห์ที่ลึกมาก ตัวอย่าง issue ของ Go ที่ผมชอบมาก: Go github issue #45624 ถกกัน 4 ปีกว่าจะได้ข้อสรุป มันอาจช้า แต่ก็ตรวจสอบทั้งความสอดคล้อง การออกแบบ และการใช้งานในโค้ดจริงอย่างละเอียด ผมคิดว่ามันช้าเท่าที่จำเป็น และผลลัพธ์ที่ได้ก็มักมีคุณภาพสูงมากRust ก็คล้ายกัน มีฟีเจอร์ที่มีประโยชน์มากจำนวนหนึ่งที่อยู่แค่ใน nightly rust และยังไม่เข้า stable (เช่น generator) มันน่าหงุดหงิด แต่ฟีเจอร์ที่เข้า stable จะผ่านการตรวจสอบอย่างลึกมาก ผมเองใจร้อน แต่ก็คิดว่าแนวทางของทีม Rust นั้นเหมาะสม
ก่อน Go 1.0 มันไม่ได้ช้าขนาดนั้น ถึงจะไม่ได้เปลี่ยนระดับรากฐานบ่อยนัก แต่ก็มีการเปลี่ยนใหญ่เกิดขึ้นบ่อย (เช่น ตัด semicolon ออก เปลี่ยนประเภท error ฯลฯ) และยังมีเครื่องมือแปลงโค้ดอัตโนมัติให้ด้วย พอถึง 1.0 จึงค่อยให้สัญญาเรื่องเสถียรภาพและกลายเป็นแนวทางแบบทุกวันนี้
Zig เป็นภาษาที่ผมนึกถึงเป็นอันดับแรกเวลาจะทำงาน low-level และการที่ใช้ Zig เป็น cross compiler สำหรับ C/C++ ได้ด้วยก็เจ๋งมาก
ปัญหาส่วนใหญ่ดูเหมือนเกิดจากเอกสารไม่พอหรือคุณภาพเอกสารไม่ดี
output.write("hello")แต่ในทางปฏิบัติกลับทำให้คนสับสน เพราะอธิบายวิธีใช้งานไม่พอ และก็ยังสงสัยด้วยว่าจำเป็นไหมที่ standard library ต้องแสดงระบบ type ที่ซับซ้อนขนาดนี้ ทั้งที่ Zig โดยรวมเต็มไปด้วยเมธอดที่ชัด กระชับ และอ่านง่าย แต่ระบบ IO ใหม่นี้กลับห่างไกลจากสิ่งนั้นและไม่เป็นธรรมชาติ(ระบบใหม่ของ zig) มีปัญหาตรงที่เอาแนวคิดที่เดิมมีไว้แค่แบ่งขอบเขตการทำงาน มาผสมเข้ากับ runtime engine ทั้งหมด แต่กลับไม่อธิบายให้ชัดว่าจะเชื่อมสองฝั่งนั้นเข้าหากันอย่างไร