Clarify format! implicit positional references

It was a little ambiguous before how explicitl positional parameters and
implicit positional parameters intermingled, and this clarifies how the two
intermingle. This also updates a little bit of documentation/code examples
elsewhere as well.
This commit is contained in:
Alex Crichton 2013-09-30 20:16:23 -07:00
parent 8174618a05
commit 23cb72b459
1 changed files with 42 additions and 19 deletions

View File

@ -40,7 +40,7 @@ format!("The number is {:d}", 1) // => ~"The number is 1"
format!("{:?}", ~[3, 4]) // => ~"~[3, 4]"
format!("{value}", value=4) // => ~"4"
format!("{} {}", 1, 2) // => ~"1 2"
```
```
From these, you can see that the first argument is a format string. It is
required by the compiler for this to be a string literal; it cannot be a
@ -56,6 +56,21 @@ example, the format string `{} {} {}` would take three parameters, and they
would be formatted in the same order as they're given. The format string
`{2} {1} {0}`, however, would format arguments in reverse order.
Things can get a little tricky once you start intermingling the two types of
positional specifiers. The "next argument" specifier can be thought of as an
iterator over the argument. Each time a "next argument" specifier is seen, the
iterator advances. This leads to behavior like this:
```rust
format!("{1} {} {0} {}", 1, 2) // => ~"2 1 1 2"
```
The internal iterator over the argument has not been advanced by the time the
first `{}` is seen, so it prints the first argument. Then upon reaching the
second `{}`, the iterator has advanced forward to the second argument.
Essentially, parameters which explicitly name their argument do not affect
parameters which do not name an argument in terms of positional specifiers.
A format string is required to use all of its arguments, otherwise it is a
compile-time error. You may refer to the same argument more than once in the
format string, although it must always be referred to with the same type.
@ -67,9 +82,17 @@ function, but the `format!` macro is a syntax extension which allows it to
leverage named parameters. Named parameters are listed at the end of the
argument list and have the syntax:
```
```
identifier '=' expression
```
```
For example, the following `format!` expressions all use named argument:
```rust
format!("{argument}", argument = "test") // => ~"test"
format!("{name} {}", 1, name = 2) // => ~"2 1"
format!("{a:s} {c:d} {b:?}", a="a", b=(), c=3) // => ~"a 3 ()"
```
It is illegal to put positional parameters (those without names) after arguments
which have names. Like positional parameters, it is illegal to provided named
@ -84,9 +107,9 @@ and if all references to one argument do not provide a type, then the format `?`
is used (the type's rust-representation is printed). For example, this is an
invalid format string:
```
```
{0:d} {0:s}
```
```
Because the first argument is both referred to as an integer as well as a
string.
@ -100,9 +123,9 @@ must have the type `uint`. Although a `uint` can be printed with `{:u}`, it is
illegal to reference an argument as such. For example, this is another invalid
format string:
```
```
{:.*s} {0:u}
```
```
### Formatting traits
@ -136,7 +159,7 @@ method of the signature:
```rust
fn fmt(value: &T, f: &mut std::fmt::Formatter);
```
```
Your type will be passed by-reference in `value`, and then the function should
emit output into the `f.buf` stream. It is up to each format trait
@ -157,7 +180,7 @@ writeln! // same as write but appends a newline
print! // the format string is printed to the standard output
println! // same as print but appends a newline
format_args! // described below.
```
```
#### `write!`
@ -172,7 +195,7 @@ use std::rt::io;
let mut w = io::mem::MemWriter::new();
write!(&mut w as &mut io::Writer, "Hello {}!", "world");
```
```
#### `print!`
@ -183,7 +206,7 @@ output. Example usage is:
```rust
print!("Hello {}!", "world");
println!("I have a newline {}", "character at the end");
```
```
#### `format_args!`
This is a curious macro which is used to safely pass around
@ -199,7 +222,7 @@ use std::fmt;
format_args!(fmt::format, "this returns {}", "~str");
format_args!(|args| { fmt::write(my_writer, args) }, "some {}", "args");
format_args!(my_fn, "format {}", "string");
```
```
The first argument of the `format_args!` macro is a function (or closure) which
takes one argument of type `&fmt::Arguments`. This structure can then be
@ -238,7 +261,7 @@ example:
```rust
format!("{0, select, other{#}}", "hello") // => ~"hello"
```
```
This example is the equivalent of `{0:s}` essentially.
@ -247,9 +270,9 @@ This example is the equivalent of `{0:s}` essentially.
The select method is a switch over a `&str` parameter, and the parameter *must*
be of the type `&str`. An example of the syntax is:
```
```
{0, select, male{...} female{...} other{...}}
```
```
Breaking this down, the `0`-th argument is selected upon with the `select`
method, and then a number of cases follow. Each case is preceded by an
@ -266,9 +289,9 @@ The plural method is a switch statement over a `uint` parameter, and the
parameter *must* be a `uint`. A plural method in its full glory can be specified
as:
```
```
{0, plural, offset=1 =1{...} two{...} many{...} other{...}}
```
```
To break this down, the first `0` indicates that this method is selecting over
the value of the first positional parameter to the format string. Next, the
@ -294,7 +317,7 @@ should not be too alien. Arguments are formatted with python-like syntax,
meaning that arguments are surrounded by `{}` instead of the C-like `%`. The
actual grammar for the formatting syntax is:
```
```
format_string := <text> [ format <text> ] *
format := '{' [ argument ] [ ':' format_spec ] [ ',' function_spec ] '}'
argument := integer | identifier
@ -315,7 +338,7 @@ plural := 'plural' ',' [ 'offset:' integer ] ( selector arm ) *
selector := '=' integer | keyword
keyword := 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'
arm := '{' format_string '}'
```
```
## Formatting Parameters