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:
parent
8174618a05
commit
23cb72b459
|
@ -40,7 +40,7 @@ format!("The number is {:d}", 1) // => ~"The number is 1"
|
||||||
format!("{:?}", ~[3, 4]) // => ~"~[3, 4]"
|
format!("{:?}", ~[3, 4]) // => ~"~[3, 4]"
|
||||||
format!("{value}", value=4) // => ~"4"
|
format!("{value}", value=4) // => ~"4"
|
||||||
format!("{} {}", 1, 2) // => ~"1 2"
|
format!("{} {}", 1, 2) // => ~"1 2"
|
||||||
```
|
```
|
||||||
|
|
||||||
From these, you can see that the first argument is a format string. It is
|
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
|
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
|
would be formatted in the same order as they're given. The format string
|
||||||
`{2} {1} {0}`, however, would format arguments in reverse order.
|
`{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
|
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
|
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.
|
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
|
leverage named parameters. Named parameters are listed at the end of the
|
||||||
argument list and have the syntax:
|
argument list and have the syntax:
|
||||||
|
|
||||||
```
|
```
|
||||||
identifier '=' expression
|
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
|
It is illegal to put positional parameters (those without names) after arguments
|
||||||
which have names. Like positional parameters, it is illegal to provided named
|
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
|
is used (the type's rust-representation is printed). For example, this is an
|
||||||
invalid format string:
|
invalid format string:
|
||||||
|
|
||||||
```
|
```
|
||||||
{0:d} {0:s}
|
{0:d} {0:s}
|
||||||
```
|
```
|
||||||
|
|
||||||
Because the first argument is both referred to as an integer as well as a
|
Because the first argument is both referred to as an integer as well as a
|
||||||
string.
|
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
|
illegal to reference an argument as such. For example, this is another invalid
|
||||||
format string:
|
format string:
|
||||||
|
|
||||||
```
|
```
|
||||||
{:.*s} {0:u}
|
{:.*s} {0:u}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Formatting traits
|
### Formatting traits
|
||||||
|
|
||||||
|
@ -136,7 +159,7 @@ method of the signature:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn fmt(value: &T, f: &mut std::fmt::Formatter);
|
fn fmt(value: &T, f: &mut std::fmt::Formatter);
|
||||||
```
|
```
|
||||||
|
|
||||||
Your type will be passed by-reference in `value`, and then the function should
|
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
|
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
|
print! // the format string is printed to the standard output
|
||||||
println! // same as print but appends a newline
|
println! // same as print but appends a newline
|
||||||
format_args! // described below.
|
format_args! // described below.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### `write!`
|
#### `write!`
|
||||||
|
@ -172,7 +195,7 @@ use std::rt::io;
|
||||||
|
|
||||||
let mut w = io::mem::MemWriter::new();
|
let mut w = io::mem::MemWriter::new();
|
||||||
write!(&mut w as &mut io::Writer, "Hello {}!", "world");
|
write!(&mut w as &mut io::Writer, "Hello {}!", "world");
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `print!`
|
#### `print!`
|
||||||
|
|
||||||
|
@ -183,7 +206,7 @@ output. Example usage is:
|
||||||
```rust
|
```rust
|
||||||
print!("Hello {}!", "world");
|
print!("Hello {}!", "world");
|
||||||
println!("I have a newline {}", "character at the end");
|
println!("I have a newline {}", "character at the end");
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `format_args!`
|
#### `format_args!`
|
||||||
This is a curious macro which is used to safely pass around
|
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!(fmt::format, "this returns {}", "~str");
|
||||||
format_args!(|args| { fmt::write(my_writer, args) }, "some {}", "args");
|
format_args!(|args| { fmt::write(my_writer, args) }, "some {}", "args");
|
||||||
format_args!(my_fn, "format {}", "string");
|
format_args!(my_fn, "format {}", "string");
|
||||||
```
|
```
|
||||||
|
|
||||||
The first argument of the `format_args!` macro is a function (or closure) which
|
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
|
takes one argument of type `&fmt::Arguments`. This structure can then be
|
||||||
|
@ -238,7 +261,7 @@ example:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
format!("{0, select, other{#}}", "hello") // => ~"hello"
|
format!("{0, select, other{#}}", "hello") // => ~"hello"
|
||||||
```
|
```
|
||||||
|
|
||||||
This example is the equivalent of `{0:s}` essentially.
|
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*
|
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:
|
be of the type `&str`. An example of the syntax is:
|
||||||
|
|
||||||
```
|
```
|
||||||
{0, select, male{...} female{...} other{...}}
|
{0, select, male{...} female{...} other{...}}
|
||||||
```
|
```
|
||||||
|
|
||||||
Breaking this down, the `0`-th argument is selected upon with the `select`
|
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
|
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
|
parameter *must* be a `uint`. A plural method in its full glory can be specified
|
||||||
as:
|
as:
|
||||||
|
|
||||||
```
|
```
|
||||||
{0, plural, offset=1 =1{...} two{...} many{...} other{...}}
|
{0, plural, offset=1 =1{...} two{...} many{...} other{...}}
|
||||||
```
|
```
|
||||||
|
|
||||||
To break this down, the first `0` indicates that this method is selecting over
|
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
|
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
|
meaning that arguments are surrounded by `{}` instead of the C-like `%`. The
|
||||||
actual grammar for the formatting syntax is:
|
actual grammar for the formatting syntax is:
|
||||||
|
|
||||||
```
|
```
|
||||||
format_string := <text> [ format <text> ] *
|
format_string := <text> [ format <text> ] *
|
||||||
format := '{' [ argument ] [ ':' format_spec ] [ ',' function_spec ] '}'
|
format := '{' [ argument ] [ ':' format_spec ] [ ',' function_spec ] '}'
|
||||||
argument := integer | identifier
|
argument := integer | identifier
|
||||||
|
@ -315,7 +338,7 @@ plural := 'plural' ',' [ 'offset:' integer ] ( selector arm ) *
|
||||||
selector := '=' integer | keyword
|
selector := '=' integer | keyword
|
||||||
keyword := 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'
|
keyword := 'zero' | 'one' | 'two' | 'few' | 'many' | 'other'
|
||||||
arm := '{' format_string '}'
|
arm := '{' format_string '}'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Formatting Parameters
|
## Formatting Parameters
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue