Skip to content
CryoCryo home
StdlibText and data

fmt

fmt turns values into text. Display is human-readable output for end users; Debug is developer-readable output for diagnostics. Both write through a Formatter<W> sitting on any FmtWrite sink, so formatting to stdout, into a String, or out to a file is the same code path.

public module fmt::error;
public module fmt::write;
public module fmt::float;
public module fmt::display;
public module fmt::spec;
public module fmt::interp;

The print family lives directly in this module — import std::fmt; brings it in. Note that it is not in the prelude.

FileWhat it holdsImport
displayDisplay, Debug, Formatter<W>, format_to_stringimport std::fmt::display;
writeFmtWrite, the sink traitimport std::fmt::write;
errorFmtErrorimport std::fmt::error;
floatf64::to_buf and friends, parse_f64import std::fmt::float;
specFmtSpec, the parsed form of an f-string format specimport std::fmt::spec;
interpThe f-string runtime(injected by the compiler wherever an f-string appears)

Printing

Two flavours, and the distinction matters.

print / println / eprint / eprintln are Display-based. They take an already-formatted owned String, write it, and drop it. Because the f-string desugar has already run each hole through Display or Debug, there is no format string left to interpret — a % in the text is data, not a directive.

import std::fmt;

println(f"connected to {host}:{port}");
println("plain text works too");        // string literals convert implicitly
eprintln(f"failed: {err:?}");

printf / eprintf are the C-style variadic forms with %s and %d specifiers, returning the byte count (negative on error, per the libc convention). Reach for these when the output is genuinely variadic; prefer an f-string otherwise. format is the same thing into a freshly allocated C string — it returns null when formatting or allocation fails, and the result is yours to free.

Both flavours go through the real stdout, so their output stays interleaved rather than landing on a second FILE*.

function print(text: String) -> void;

Write an already-formatted String (typically an f-string f"{x}") to stdout, then drop it. Display-based counterpart to printf: the f-string desugar already ran each {expr} through Display/Debug, so there is no format string to interpret here (a % in the text is data, not a directive). We go through the real stdout (printf "%.*s") so output stays interleaved with printf rather than landing on a second FILE*.

function println(text: String) -> void;

Like print, followed by a newline.

function eprint(text: String) -> void;

Write an already-formatted String (typically an f-string) to stderr, then drop it. Display-based counterpart to eprintf.

function eprintln(text: String) -> void;

Like eprint, followed by a newline.

function printf(fmt: string, args...) -> i32;

Write a printf-style formatted string to stdout. Returns the number of bytes written, or a negative value on error (libc printf convention). Use this for genuinely variadic %s/%d output; for value formatting prefer an f-string through println (Display-based) below.

function eprintf(fmt: string, args...) -> i32;

Write a printf-style formatted string to stderr. Same specifier rules as printf (see above). Returns the number of bytes vfprintf reported.

function format(fmt: string, args...) -> string;

Format printf-style into a freshly allocated string. Returns null when the formatting or the allocation failed.