Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the dollar syntax mean in a Rust format string?

I'm going through Rust by Example and the use of $ (the dollar sign) in this example isn't clear to me:

// You can right-align text with a specified width. This will output
// "     1". 5 white spaces and a "1".
println!("{number:>width$}", number=1, width=6);

// You can pad numbers with extra zeroes. This will output "000001".
println!("{number:>0width$}", number=1, width=6);

I found this in the documentation for std::fmt, but it doesn't clarify things for me:

format_string := <text> [ maybe-format <text> ] *
maybe-format := '{' '{' | '}' '}' | <format>
format := '{' [ argument ] [ ':' format_spec ] '}'
argument := integer | identifier

format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type]
fill := character
align := '<' | '^' | '>'
sign := '+' | '-'
width := count
precision := count | '*'
type := identifier | ''
count := parameter | integer
parameter := argument '$'

Poking around at the code a bit, I've found that it doesn't compile without the dollar sign, but "width" can be replaced with any arbitrary identifier. i.e. the following is equivalent to the third line in the first code block:

println!("{number:>test$}", number=1, test=6);
like image 825
Fred Avatar asked Sep 18 '17 14:09

Fred


People also ask

What is dollar sign in Rust?

The arguments of a macro are prefixed by a dollar sign $ and type annotated with a designator: macro_rules! create_function { // This macro takes an argument of designator `ident` and. // creates a function named `$func_name`.

What does format do in Rust?

Creates a String using interpolation of runtime expressions.

Does format return a string rust?

Functions. The format function takes an Arguments struct and returns the resulting formatted string. The write function takes an output stream, and an Arguments struct that can be precompiled with the format_args! macro.


1 Answers

It allows the width or precision of another formatted item to be provided as an argument instead of hard-coded as part of the format string. The parameter can be specified using a numeric index or a name.

The documentation says:

The value for the width can also be provided as a [usize] in the list of parameters by using the dollar syntax indicating that the second argument is a [usize] specifying the width, for example:

// All of these print "Hello x    !"
println!("Hello {:5}!", "x");
println!("Hello {:1$}!", "x", 5);
println!("Hello {1:0$}!", 5, "x");
println!("Hello {:width$}!", "x", width = 5);

Referring to an argument with the dollar syntax does not affect the "next argument" counter, so it's usually a good idea to refer to arguments by position, or use named arguments.

It also says:

There are three possible ways to specify the desired precision:

[...]

  1. An integer or name followed by dollar sign .N$:

    use format argument N (which must be a usize) as the precision.

[...]

For example, the following calls all print the same thing Hello x is 0.01000:

// Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
println!("Hello {0} is {1:.5}", "x", 0.01);

// Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
println!("Hello {1} is {2:.0$}", 5, "x", 0.01);

// Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
println!("Hello {0} is {2:.1$}", "x", 5, 0.01);

// Hello {next arg ("x")} is {second of next two args (0.01) with precision
//                          specified in first of next two args (5)}
println!("Hello {} is {:.*}",    "x", 5, 0.01);

// Hello {next arg ("x")} is {arg 2 (0.01) with precision
//                          specified in its predecessor (5)}
println!("Hello {} is {2:.*}",   "x", 5, 0.01);

// Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
//                          in arg "prec" (5)}
println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
like image 88
Shepmaster Avatar answered Nov 15 '22 10:11

Shepmaster