// title = Zig // pubDate = 2026-09-01 // nodes = zig // description = Learning notes for zig programming language const std = @import("std"); const Io = std.Io; // | Different ways to print // // > The methods mentioned here are by no means exhaustive. // // || Debug print // // Writes to stderr and ignores errors (hence no `try`), bypasses the `Io` interface. // Ideally we should delete every occurence of `std.debug.print` after debugging. fn @"std-debug-print"() void { std.debug.print("Hello, {s}!\n", .{"std.debug.print"}); } // || [Io.Writer](https://ziglang.org/documentation/master/std/#std.Io.Writer) // // > You'd probably want to watch // [this talk](https://youtu.be/f30PceqQWko?si=KIHJCgBYx7sStJk8) // by Andrew Kelly and // [this post](https://joegm.github.io/blog/inside-zigs-new-writer-interface/#one-writer-to-rule-them-all) // by Joe Mckay. // // `Io.File.stderr().writerStreaming(io, &buffer)` returns `Io.File.Writer` and we can // use its `interface` i.e. `Io.Writer` to actually write to `stderr`, the buffer we // hand is managed through the interface (*buffering in the interface*). And don't forget // to `flush`. // // > There are two modes streaming and no-streaming for `Io.File.Writer`. We should take // the streaming variant for stdout/stderr(/stdin). fn @"std-Io-Writer"(io: Io) !void { var stderr_buf: [1024]u8 = undefined; var stderr_writer = Io.File.stderr().writerStreaming(io, &stderr_buf); const stderr = &stderr_writer.interface; defer stderr.flush() catch {}; try stderr.print("Hello, {s}!\n", .{"std.Io.Writer"}); } // ||| [Thread-safe stderr](https://ziglang.org/documentation/master/std/#std.debug.lockStderr) // // `std.debug.lockStderr` allows the caller to freely write to stderr until unlockStderr // is called. During the lock, any `std.Progress` information is cleared from the // standard stream. As `std.debug.print`, this ignores `Io` and should be deleted after // debugging. fn @"std-debug-lockStderr"() !void { const stderr = std.debug.lockStderr(&.{}).terminal().writer; defer std.debug.unlockStderr(); // flushing is performed automatically try stderr.print("Hello, {s}!\n" , .{"std.debug.lockStderr"}); } // Alternatively we can use `std.Io.lockStderr` to perform application-level writes // to stderr. fn @"std-Io-lockStderr"(io: Io) !void { var stderr_buf: [1024]u8 = undefined; var locked = try io.lockStderr(&stderr_buf, null); defer io.unlockStderr(); const stderr = locked.terminal().writer; try stderr.print("Hello, {s}!\n" , .{"std.Io.lockStderr"}); } // To conclude, use `debug` for informal/debug-only diagnostics. Take a lock when e.g. // a multi-write writer mustn't interleave with other writers. // %% // ϗ zig build-exe zig-notes.zig && ./zig-notes // Hello, std.debug.print! // Hello, std.Io.Writer! // Hello, std.debug.lockStderr! // Hello, std.Io.lockStderr! // %% pub fn main(init: std.process.Init) !void { @"std-debug-print"(); try @"std-Io-Writer"(init.io); try @"std-debug-lockStderr"(); try @"std-Io-lockStderr"(init.io); } // TODO // // - `Io.Reader` & `Io.Writer` // - reflexion