2.2 Print-macros

When we first wrote our ‘Hello, world!’ program, we used something called a macro to print text to the console. The specific macro we used in order to achieve that’s called println!, but is slightly more powerful than we’ve went over so far.

The println! is not Rust’s only macro. There’s a whole bunch of them contained by Rust’s standard library—all used for different purposes.

Printing

In order to print something to the screen, you may use the print! macro. Should you want to have a new line appended after you have outputted something into the console, you may use println!, rather than print!. They’re the same, only println! puts a new line after printing out a specified string of text:

print!("<I’m on this line>");
println!("<I’m on the same line>");
print!("<My comrade pushed me off>");

Do keep in mind that this requires to be put inside your main function. Writing it without the main function inside this text means it’ll look somewhat cleaner.

The above will be outputted into the console as:

<I’m on this line><I’m on the same line>
<My comrade pushed me off>

Usually when creating console applications, you’ll want to have a new line following every single piece of text you output—so use println!.

Arguments

You can enter more arguments into the macros handling printing in order to print out the values of variable bindings. This works quite similarly to how it would be done in a C-family language using printf—or even more similarly to the way langauges such as Python handles output into the console: which could seem strange as Rust is nowhere as high-level as Python. We’re going to have to thank Rust’s development team for giving us such great tools when it comes to printing things into the console!

In order to print a value of a variable bindings out, there needs be curly braces ‘{}’ as placeholders for where binding names will be put:

let x = 5;

println!("x is {}.", x);

The above will be validated and outputted into the console like so:

x is 5.

Should you want to print out multiple variables at the same time, you may add more placeholders:

let (x, y) = (3, 4);

println!("The battleship coordinates are ({}, {})", x, y);

How nice—you’re leaving out coordinates for army battleships!

Keep in mind that all placeholders need to be linked together with a variable bindings, otherwise we will run into an error. More on how the arguments inside print-macros may be formatted are covered in the Formatting section.

Panic!

There’s another macro which may be used to print thigns to the screen—although it has a slight twist. Whenever panic! is called upon, it first prints our a message we provide it with—an error message to be exact—followed by exiting our application:

panic!("An error has occured.");

This will output our custom error message into the console before shutting the application off:

thread 'main' panicked at 'An error has occurred.', src\main.rs:5

The panic! macro is used all over Rust’s standard library, usually used for exception handling—error handling that is.

If we wanted to, we could provide the panic! macro with some placeholders:

let x = 3;

panic!("Battleship at ({}, {}) crashed your application.", x, 4);

This way we can create really detailed straight on error messages.

Exercises

  • Play with macros until you get bored.

Moreover

Rust macros are rather nice, especially when it comes to printing. Macros are explored more thoroughly in the Macros section—as well as a whole lot of other useful macros from Rust’s standard library.