RustArena

Step 4 of 6

Printing structs with Debug

Try to print a struct with {} and Rust refuses:

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 1, y: 2 };
    println!("{}", p);
}
error[E0277]: `Point` doesn't implement `std::fmt::Display`

{} uses Display, the "pretty, for end users" format. Rust doesn't guess how your type should look to users ((1, 2)? x=1 y=2?), so you'd have to write that yourself, which you'll learn in the traits module. {:?} uses Debug, the "for programmers" format, and for that Rust can write the code for you.

#[derive(Debug)]

#[derive(Debug)]
struct Item {
    name: String,
    price_cents: u32,
    in_stock: bool,
}

fn main() {
    let item = Item {
        name: String::from("Tea"),
        price_cents: 450,
        in_stock: true,
    };
    println!("{:?}", item);
    println!("{:#?}", item);
    if item.in_stock {
        println!("{} costs {} cents", item.name, item.price_cents);
    }
}
Item { name: "Tea", price_cents: 450, in_stock: true }
Item {
    name: "Tea",
    price_cents: 450,
    in_stock: true,
}
Tea costs 450 cents

dbg!

dbg!(expression) prints the file, the line, the expression and its value, then returns the value, so you can wrap it around something in the middle of your code:

#[derive(Debug)]
struct Item {
    name: String,
    price_cents: u32,
}

fn main() {
    let price_cents = dbg!(150 * 3);
    let item = Item { name: String::from("Tea"), price_cents };
    dbg!(&item);
    println!("{} costs {}", item.name, item.price_cents);
}
Tea costs 450

The dbg! lines go to standard error (stderr), not standard output, so they don't mix with the program's real output (and the tests on this site ignore them). In a terminal you'd see:

[src/main.rs:8:23] 150 * 3 = 450
[src/main.rs:10:5] &item = Item {
    name: "Tea",
    price_cents: 450,
}

Pass a reference (dbg!(&item)): dbg!(item) would move item into the macro. dbg! is for debugging sessions; remove it before you commit (many teams turn on clippy's dbg_macro lint to catch leftovers).

Comparing with ==

== doesn't work on your struct either until you derive PartialEq, which compares field by field. You can derive several things at once: #[derive(Debug, PartialEq)]. assert_eq! needs both: PartialEq to compare and Debug to show the two values when they differ.

#[derive(Debug, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let a = Point { x: 1, y: 2 };
    let b = Point { x: 1, y: 2 };
    println!("{}", a == b);
    println!("{}", a == Point { x: 2, y: 1 });
}
true
false

Common mistakes

Your task

Fill in the blanks: derive the trait that {:?} needs, and print p with it. The program should print:

sum: 1
Point { x: 3, y: -2 }

Challenge 2

Add one derive line so that Item can be pretty-printed and compared with ==. Then print a with the pretty Debug format and print whether a == b, so the output is exactly:

Item {
    name: "bolt",
    qty: 40,
}
same: true

Challenge 3

Write two functions for 2D points:

The hidden tests compare whole points with assert_eq!, so Point needs the right derives. Add them yourself.

Previous: Building structs with shorthand and update syntax Next: Tuple structs, newtypes and unit structs