Why does the println! function use an exclamation mark in Rust?

In Swift, ! means to unwrap an optional (possible value).


Solution 1:

println! is not a function, it is a macro. Macros use ! to distinguish them from normal method calls. The documentation contains more information.

See also:

  • What is the difference between macros and functions in Rust?

Rust uses the Option type to denote optional data. It has an unwrap method.

Rust 1.13 added the question mark operator ? as an analog of the try! macro (originally proposed via RFC 243).

An excellent explanation of the question mark operator is in The Rust Programming Language.

fn foo() -> Result<i32, Error> {
    Ok(4)
}

fn bar() -> Result<i32, Error> {
    let a = foo()?;
    Ok(a + 4)
}

The question mark operator also extends to Option, so you may see it used to unwrap a value or return None from the function. This is different from just unwrapping as the program will not panic:

fn foo() -> Option<i32> {
    None
}

fn bar() -> Option<i32> {
    let a = foo()?;
    Some(a + 4)
}

Solution 2:

println! is a macro in rust, that means that rust will rewrite the code for you at compile time.

For example this:

fn main() {
    let x = 5;
    println!("{}", x);
}

Will be converted to something like this at compile time:

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;
fn main() {
    let x = 5;
    {
        ::std::io::_print(::core::fmt::Arguments::new_v1(
            &["", "\n"],
            &match (&x,) {
                (arg0,) => [::core::fmt::ArgumentV1::new(
                    arg0,
                    ::core::fmt::Display::fmt,
                )],
            },
        ));
    };
}

*Notice that the &x is passed as a reference.

It's a macro because it does things that functions can't do:

  • It parses the format string at compile time, and generates type safe code
  • It has a variable number of arguments
  • It has named arguments ("keyword arguments")
    println!("My name is {first} {last}", first = "John", last = "Smith");
    

sources:

  • https://doc.rust-lang.org/rust-by-example/hello/print.html.
  • https://www.reddit.com/r/rust/comments/4qor4o/newb_question_why_is_println_a_macro/
  • Does println! borrow or own the variable?