Before we can write hello_world.rs
, we need to know how to output data. In Rust, we use println!
, which does formatted printing like printf
in Java and C. Rather than %
placeholders, the format string uses curly braces:
fn main() {
// prints 3 + 5 = 8
println!("{} + {} = {}", 3, 5, 3 + 5);
}
Each {}
placeholder is replaced by the string representation of the next positional parameter. To get more control over the format or to select a different parameter, we insert commands (which adhere to a grammar) within the braces. Roughly, each placeholder has this grammatical form:
{selector:formatting}
The selector may be omitted if we are dropping in parameters in positional order. The separator :
and the formatting flags may be omitted if we are satisfied with the default formatting.
The following calls demonstrate how we might express selectors and common formatting parameters:
println!("{1} {0}", 'x', 'y'); // prints "y x"
println!("{:<7}", 0); // prints "0 "
println!("{:>7}", 0); // prints " 0"
println!("{:^7}", 0); // prints " 0 "
println!("{:_^7}", 0); // prints "___0___"
println!("{:.4}", 0.123); // prints "0.1230"
println!("{:>9.4}", 0.123); // prints " 0.1230"
println!("{:?}", (5, true)); // prints "(5, true)"
Not all types have string representations. For example, if we had plain {}
on the last call, which prints a tuple, the code wouldn't compile. Tuples don't have string representations. However, most types do have a debugging representation that we request with the ?
formatting flag.
The first parameter to println!
must always be a literal string because the compiler typechecks the placeholders statically to ensure that they align with their corresponding parameters.
An identifier that ends in !
is a macro, not a function. A macro is shorthand code that is expanded to other source code at compile time—not at runtime. We have seen in C and C++ the #include
macro, which expands to the contents of the included file. The println!
macro expands to some complex code that actually does the output. When we discuss Rust's memory system, we will see why println!
is easier to use as a macro rather than a function.