std.fmt
API summary (generated from the Beans source by npm run coverage): 7 package functions · 1 type · 1 constructor · 11 instance methods.
std.fmt turns numbers into text in the shapes you often need: hexadecimal,
binary, grouped digits, padded columns, and fixed decimal places. Three functions
are written in Beans at
stdlib/std/fmt/fmt.b;
the other four are native and typed in the compiler, so their parameters are
positional and carry no names.
import std.fmtBase conversions (Beans source)
Section titled “Base conversions (Beans source)”pub fn hex(value: int) -> stringpub fn binary(value: int) -> stringpub fn group_digits(value: int, separator: string) -> stringhexgives lowercase hex of the 64-bit pattern, with no0xprefix, and"0"for zero. It works on the raw u64 bit pattern, so a negative int shows its two’s complement form.binarygives the base-2 text of the value.group_digitsinsertsseparatorevery three digits from the right, and keeps a leading-for negative numbers.
import std.ioimport std.fmt
fn main() { io.println(fmt.hex(255)) // ff io.println(fmt.binary(6)) // 110 io.println(fmt.group_digits(1234567, ",")) // 1,234,567 io.println(fmt.group_digits(-1000, ",")) // -1,000}Padding (native)
Section titled “Padding (native)”pad_left(string, int) -> stringpad_right(string, int) -> stringThe second argument is the target width. pad_left(s, width) pads s with
spaces on the left; pad_right(s, width) pads on the right. Padding is by byte
width. If the input is already at least width bytes wide, it is returned
unchanged. A huge width panics.
import std.ioimport std.fmt
fn main() { io.println(fmt.pad_left("7", 4)) // " 7" io.println(fmt.pad_right("7", 4)) // "7 "}Decimals (native)
Section titled “Decimals (native)”float(float, int) -> stringdecimal(decimal, int) -> stringThe second argument is the number of decimal places, from 0 to 100. float gives
a fixed number of decimal places. decimal is exact: when it needs to show fewer
places than the value has, it rounds half-even (banker’s rounding); when it needs
more, it zero-pads. For example fmt.decimal(19.995, 2) is "20.00".
import std.ioimport std.fmt
fn main() { io.println(fmt.float(3.14159, 2)) // 3.14 io.println(fmt.decimal(19.995, 2)) // 20.00}See Numbers and decimal for the decimal type
itself.
StringBuilder
Section titled “StringBuilder”Interpolation renders one value. A builder accumulates a stream of them into one
buffer, which is the difference between O(n) and O(n²) when you are building a
string in a loop: text = "{text}piece" copies everything written so far on
every turn, while a builder appends and converts once.
new StringBuilder(capacity: int = 0)
pub fn push(text: string)pub fn push_line(text: string)pub fn push_int(value: int)pub fn push_bool(value: bool)pub fn push_byte(value: int)pub fn len() -> intpub fn is_empty() -> boolpub fn reserve(capacity: int)pub fn clear()pub fn to_string() -> stringpub fn to_bytes() -> Bytespushappends text.push_lineappends it followed by a newline.push_int,push_boolandpush_byteappend a value without going through interpolation first —push_bytewrites one raw byte.lenis the number of bytes accumulated so far, not characters, andis_emptyislen() == 0.reservegrows the buffer up front when you know roughly how much is coming;clearempties it and keeps the capacity, so one builder can be reused across rounds.to_stringconverts once at the end.to_byteshands back the raw buffer instead, for a caller that wants bytes.
The buffer holds bytes and nothing here validates UTF-8, exactly as Bytes
does not. Anything already rendered — by interpolation, or by fmt.float,
fmt.decimal or fmt.pad_left above — goes in with push.
import std.ioimport std.fmt
fn main() { var out: fmt.StringBuilder = new fmt.StringBuilder(64) var index: int = 0 for index < 3 { out.push("row ") out.push_int(index) out.push_line("") index += 1 } io.print(out.to_string()) io.println(out.len()) // 18 out.clear() io.println(out.is_empty()) // true}Format specs in interpolation
Section titled “Format specs in interpolation”String interpolation understands the same width and precision specs, so you often
do not need to call these functions at all. Inside "{ ... }":
| Spec | Meaning |
|---|---|
{x:8} | right-align x in a field 8 wide |
{x:-8} | left-align x in a field 8 wide |
{pi:.2} | two decimal places |
{pi:8.2} | width 8 and two decimal places |
These render the same way as pad_left / pad_right and float above.
import std.io
fn main() { let pi: float = 3.14159 io.println("[{pi:8.2}]") // [ 3.14]}