Zig has no built-in print function or statement.
If you want to print something quickly, you can use std.debug.print
:
const std = @import("std");
pub fn main() void {
std.debug.print("Hello World!", .{});
}
Why is there no built-in function like C's printf
?
One answer is that, unlike C, Zig doesn't need to special-case the printing function. In C, printf
could not be implemented as a normal function without losing its special compile-time checks (i.e., the compiler can check that the number of arguments passed to printf
matches the number of %
placeholders in the format string).
In Zig all of that can be implemented in userland using comptime checks.
Another reason why Zig has no built-in print function is that printing is less obvious than what some other languages would lead you to believe.
When printing becomes actually important
When you are just printing a debug line to the console, you don't care about handling error conditions, but sometimes printing to the terminal is the core functionality of your application and at that point, to write a robust tool, you will need to design for failure.
On top of that there might be performance implications related to buffering, or you might be sharing the output stream with other threads, at which point a lock might (or might not) be necessary to ensure that the printed information keeps making sense.
Earlier we saw std.debug.print
and that function made some choices for us:
- it prints to stderr
- it has a lock in case you have multiple threads
- it does not buffer
- errors get discarded
This is its implementation (from the stdlib):
pub fn print(comptime fmt: []const u8, args: anytype) void {
const held = stderr_mutex.acquire();
defer held.release();
const stderr = io.getStdErr().writer();
nosuspend stderr.print(fmt, args) catch return;
}
Printing more reliably
To print in a more reliable way, you can use std.log
, which also works as a more complete logging system with support for different scopes and levels. You can read more about it in the stdlib.
Printing to stdout
If you want to have direct access to stdout, you can use std.io.getStdOut()
and from there use the writer
interface to print, just like the code above does with stderr. At that point it will be up to you if you want to have buffering (using a std.io.BufferedWriter
) or a lock, and you will also have to decide what to do with errors.
Watch the talk
If you want to listen to me give a full talk just on this topic, here you go :^)
Discussion (0)