175 lines
4.3 KiB
Racket
175 lines
4.3 KiB
Racket
#lang scribble/manual
|
|
|
|
@(require scribble/manual
|
|
;scribble/class
|
|
scribble/eval
|
|
(for-label racket/base
|
|
))
|
|
|
|
@(define the-eval
|
|
(make-base-eval))
|
|
|
|
|
|
@title{sprintf functions}
|
|
@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]]
|
|
|
|
@defmodule[sprintf]
|
|
|
|
This module provides a compact @tt{printf}-style string
|
|
formatting facility for Racket.
|
|
It is inspired by C-style format strings, but implemented
|
|
on top of @racket[racket/format].
|
|
|
|
The core functionality is provided by @racket[sprintf]
|
|
and @racket[sprintf*].
|
|
|
|
@section{Overview}
|
|
|
|
The module exports two formatting functions:
|
|
|
|
@itemlist[
|
|
@item{@racket[sprintf] — formats using variadic arguments}
|
|
@item{@racket[sprintf*] — formats using an explicit argument list}
|
|
]
|
|
|
|
Both functions use the same format-string syntax and semantics.
|
|
|
|
@section{Exports}
|
|
|
|
@defproc[(sprintf [format string?] [arg any/c] ...) string?]{
|
|
Formats the string @racket[format] by substituting the given
|
|
arguments according to printf-style conversion specifications.
|
|
|
|
Arguments are consumed sequentially from left to right.
|
|
An error is raised if there are too many or too few arguments
|
|
for the format string.
|
|
}
|
|
|
|
@defproc[(sprintf* [format string?] [args list?]) string?]{
|
|
Variant of @racket[sprintf] where the arguments are supplied
|
|
explicitly as a list.
|
|
|
|
This form is useful when arguments are constructed dynamically
|
|
or passed through higher-order functions.
|
|
}
|
|
|
|
@section{Format String Syntax}
|
|
|
|
A format specification has the general form:
|
|
|
|
@verbatim{
|
|
%[flags][width][.precision][length]type
|
|
}
|
|
|
|
Only a well-defined subset of the traditional @tt{printf}
|
|
syntax is supported.
|
|
|
|
@section{Supported Conversion Types}
|
|
|
|
The following conversion specifiers are recognized:
|
|
|
|
@itemlist[
|
|
@item{@tt{%d} — decimal integer}
|
|
@item{@tt{%x} — hexadecimal integer}
|
|
@item{@tt{%f} — floating-point number}
|
|
@item{@tt{%s} — string}
|
|
@item{@tt{%%} — literal percent sign}
|
|
]
|
|
|
|
@section{Flags}
|
|
|
|
The following flags are supported:
|
|
|
|
@itemlist[
|
|
@item{@tt{0} — pad numeric output with zeros instead of spaces}
|
|
@item{@tt{-} — left-align the result within the field width}
|
|
]
|
|
|
|
If no flag is specified, numeric values are right-aligned and
|
|
padded with spaces.
|
|
|
|
@section{Field Width}
|
|
|
|
A minimum field width may be specified as a decimal number:
|
|
|
|
@verbatim{
|
|
%8d
|
|
%-10s
|
|
}
|
|
|
|
If the formatted value is shorter than the field width, it is
|
|
padded according to the alignment rules.
|
|
|
|
@section{Dynamic Width and Precision}
|
|
|
|
Both width and precision may be specified using @tt{*}.
|
|
In that case, the value is taken from the argument list.
|
|
|
|
Example:
|
|
|
|
@verbatim{
|
|
(sprintf "%*.*f" 8 3 1.23456)
|
|
}
|
|
|
|
In this example:
|
|
@itemlist[
|
|
@item{the first argument specifies the field width}
|
|
@item{the second argument specifies the precision}
|
|
@item{the third argument is the value to be formatted}
|
|
]
|
|
|
|
The arguments supplying width or precision must be numbers;
|
|
otherwise an error is raised.
|
|
|
|
@section{Precision}
|
|
|
|
Precision has different meanings depending on the conversion type:
|
|
|
|
@itemlist[
|
|
@item{for numeric conversions, it controls the number of digits after the decimal point}
|
|
@item{for strings, it specifies the maximum output width}
|
|
]
|
|
|
|
If no precision is specified:
|
|
@itemlist[
|
|
@item{numeric values default to precision 0 for integers}
|
|
@item{strings are not truncated}
|
|
]
|
|
|
|
@section{Length Modifiers}
|
|
|
|
The length modifier field (e.g. @tt{l}) is parsed for syntactic
|
|
compatibility but otherwise ignored.
|
|
It has no semantic effect.
|
|
|
|
@section{Type Checking and Errors}
|
|
|
|
The formatter performs runtime type checking:
|
|
|
|
@itemlist[
|
|
@item{numeric conversion specifiers require numeric arguments}
|
|
@item{@tt{%s} requires a string argument}
|
|
]
|
|
|
|
Errors are raised in the following situations:
|
|
|
|
@itemlist[
|
|
@item{arguments remain but no format specifiers are left}
|
|
@item{format specifiers remain but no arguments are left}
|
|
@item{@tt{*} is used but no corresponding numeric argument is available}
|
|
@item{argument types do not match the conversion specifier}
|
|
]
|
|
|
|
Error messages are designed to be explicit and descriptive.
|
|
|
|
@section{Implementation Notes}
|
|
|
|
Internally, the formatter uses regular-expression driven parsing
|
|
and delegates the actual formatting to @racket[~r] and @racket[~a]
|
|
from @racket[racket/format].
|
|
|
|
The implementation is intentionally strict: mismatches between
|
|
format strings and arguments are treated as programming errors
|
|
and reported immediately.
|
|
|