- Source: Format (Common Lisp)
Format is a function in Common Lisp that can produce formatted text using a format string similar to the print format string. It provides more functionality than print, allowing the user to output numbers in various formats (including, for instance: hex, binary, octal, roman numerals, and English), apply certain format specifiers only under certain conditions, iterate over data structures, output data tabularly, and even recurse, calling format internally to handle data structures that include their own preferred formatting strings. This functionally originates in MIT's Lisp Machine Lisp, where it was based on Multics.
Specification
The format function is specified by the syntax:
format destination controlString &rest formatArguments
Directives in the control string are interpolated using the format arguments, and the thus constructed character sequence is written to the destination.
Destination
The destination may either be a stream, a dynamic string, T, or the NIL constant; the latter of which presents a special case in that it creates, formats and returns a new string object, while T refers to the standard output, usually being equivalent to the console. Streams in Common Lisp comprehend, among others, string output and file streams; hence, being capable of writing to such a variety of destinations, this function unifies capabilities distributed among distinct commands in some other programming languages, such as C's printf for console output, sprintf for string formatting, and fprintf for file writing.
The multitude of destination types is exemplified in the following:
Control String and Format Arguments
The control string may contain literal characters as well as the meta character ~ (tilde), which demarcates format directives. While literals in the input are echoed verbatim, directives produce a special output, often consuming one or more format arguments.
= Directives
=A format directive, introduced by a ~, is followed by zero or more prefix parameters, zero or more modifiers, and the directive type. A directive definition, hence, must conform to the following pattern:
~[prefixParameters][modifiers]directiveType
The directive type is always specified by a single character, case-insensitive in the case of letters. The data to be processed by a format directive, if at all necessary, is called its format argument and may be zero or more objects of any type compatible. Whether and in which quantity such data is accepted depends on the directive and potential modifiers applied unto it. The directive type ~%, for instance, abstains from the consumption of any format arguments, whereas ~D expects exactly one integer number to print, and ~@{, a directive influenced by the at-sign modifier, processes all remaining arguments.
The following directive, ~B, expects one number object from the format arguments and writes its binary (radix 2) equivalent to the standard output.
Where configurations are permissive, prefix parameters may be specified.
= Prefix parameters
=Prefix parameters enable an injection of additional information into a directive to operate upon, similar to the operation of parameters when provided to a function. Prefix parameters are always optional, and, if provided, must be located between the introducing ~ and either the modifiers or, if none present, the directive type. The values are separated by commas, but do not tolerate white spaces on either side. The number and type of these parameters depends on the directive and the influence of potential modifiers.
Two particular characters may be utilized as prefix parameter values with distinctive interpretation: v or V acts as a placeholder for an integer number or character from the format arguments which is consumed and placed into its stead. The second special character, #, is substituted by the tally of format arguments yet abiding their consumption. Both V and # enable behavior defined by dynamic content injected into the prefix parameter list.
The V parameter value introduces a functionality equivalent to a variable in the context of general programming. Given this simple scenario, in order to left-pad a binary representation of the integer number 5 to at least eight digits with zeros, the literal solution is as follows:
The first prefix parameter controlling the output width may, however, be defined in terms of the V character, delegating the parameter value specification to the next format argument, in our case 8.
Solutions of this kind are particularly a benefit if parts of the prefix parameter list shall be described by variables or function arguments instead of literals, as is the case in the following piece of code:
Even more fitting in those situations involving external input, a function argument may be passed into the format directive:
# as a prefix parameter tallies those format arguments not yet processed by preceding directives, doing so without actually consuming anything from this list. The utility of such a dynamically inserted value is preponderantly restricted to use cases pertaining to conditional processing. As the argument number can only be an integer number greater than or equal to zero, its significance coincides with that of an index into the clauses of a conditional ~[ directive.
The interplay of the special # prefix parameter value with the conditional selection directive ~[ is illustrated in the following example. The condition states four clauses, accessible via the indices 0, 1, 2, and 3 respectively. The number of format arguments is employed as the means for the clause index retrieval; to do so, we insert # into the conditional directive which permits the index to be a prefix parameter. # computes the tally of format arguments and suggests this number as the selection index. The arguments, not consumed by this act, are then available to and processed by the selected clause's directives.
= Modifiers
=Modifiers act in the capacity of flags intending to influence the behavior of a directive. The admission, magnitude of behavioral modification and effect, as with prefix parameters, depends upon the directive. In some severe cases, the syntax of a directive may be varied to a degree as to invalidate certain prefix parameters; this power especially distinguishes modifiers from most parameters. The two valid modifier characters are @ (at-sign) and : (colon), possibly in combination as either :@ or @:.
The following example illustrates a rather mild case of influence exerted upon a directive by the @ modifier: It merely ensures that the binary representation of a formatted number is always preceded by the number's sign:
Format directives
An enumeration of the format directives, including their complete syntax and modifier effects, is adduced below.
Example
An example of a C printf call is the following:
Using Common Lisp, this is equivalent to:
Another example would be to print every element of list delimited with commas, which can be done using the ~{, ~^ and ~} directives:
Note that not only is the list of values iterated over directly by format, but the commas correctly are printed between items, not after them. A yet more complex example would be printing out a list using customary English phrasing:
The ability to define a new directive through ~/functionName/ provides the means for customization. The next example implements a function which prints an input string either in lowercase, uppercase or reverse style, permitting a configuration of the number of repetitions, too.
Whilst format is somewhat infamous for its tendency to become opaque and hard to read, it provides a remarkably concise yet powerful syntax for a specialized and common need.
A Common Lisp FORMAT summary table is available.
See also
Common Lisp
Common Lisp the Language
Practical Common Lisp
On Lisp
References
Books
Common Lisp HyperSpec Section 22.3 Formatted Output
Practical Common Lisp Chapter 18. A Few FORMAT Recipes
Kata Kunci Pencarian:
- Berkas INI
- Kode operasi
- Java
- Perl
- Daftar istilah komputer
- Daftar ilmuwan komputer
- Graph database
- Format (Common Lisp)
- Common Lisp
- Embeddable Common Lisp
- Format
- Common Lisp HyperSpec
- S-expression
- Common Lisp the Language
- On Lisp
- Printf
- Double-precision floating-point format