dbg! 巨集和 .inspect

dbg! 是個非常有用的巨集,用來印出快速資訊。它是代替 println! 的好選擇,因為它輸入的速度更快,提供的資訊更多:

fn main() {
    let my_number = 8;
    dbg!(my_number);
}

印出 [src\main.rs:4] my_number = 8

但實際上,你可以把 dbg! 放在其他許多地方,甚至可以把程式碼包在裡面。查看以此為例的程式碼:

fn main() {
    let mut my_number = 9;
    my_number += 10;

    let new_vec = vec![8, 9, 10];

    let double_vec = new_vec.iter().map(|x| x * 2).collect::<Vec<i32>>();
}

這段程式碼建立新的可變數字,並且改變了它。然後再建立向量,並使用 itermapcollect 建立新的向量。我們可以把 dbg! 放在幾乎是這段程式碼的任何地方。dbg! 問編譯器:"這個當下你在做什麼?",並且告訴你:

fn main() {
    let mut my_number = dbg!(9);
    dbg!(my_number += 10);

    let new_vec = dbg!(vec![8, 9, 10]);

    let double_vec = dbg!(new_vec.iter().map(|x| x * 2).collect::<Vec<i32>>());

    dbg!(double_vec);
}

所以會印出:

[src\main.rs:3] 9 = 9

和:

[src\main.rs:4] my_number += 10 = ()

和:

[src\main.rs:6] vec![8, 9, 10] = [
    8,
    9,
    10,
]

還有這個,甚至可以秀出表示式的值:

[src\main.rs:8] new_vec.iter().map(|x| x * 2).collect::<Vec<i32>>() = [
    16,
    18,
    20,
]

和:

[src\main.rs:10] double_vec = [
    16,
    18,
    20,
]

.inspectdbg! 有點類似,用起來就像在疊代器中用 map 一樣。它給你疊代的元素,你可以印出來或者做任何你想做的事情。例如,讓我們再來看看 double_vec

fn main() {
    let new_vec = vec![8, 9, 10];

    let double_vec = new_vec
        .iter()
        .map(|x| x * 2)
        .collect::<Vec<i32>>();
}

我們想知道更多關於程式碼做了什麼的資訊。所以我們在兩個地方新增 inspect()

fn main() {
    let new_vec = vec![8, 9, 10];

    let double_vec = new_vec
        .iter()
        .inspect(|first_item| println!("The item is: {}", first_item))
        .map(|x| x * 2)
        .inspect(|next_item| println!("Then it is: {}", next_item))
        .collect::<Vec<i32>>();
}

印出:

The item is: 8
Then it is: 16
The item is: 9
Then it is: 18
The item is: 10
Then it is: 20

而且因為 .inspect 接受的是閉包,所以我們可以隨意寫:

fn main() {
    let new_vec = vec![8, 9, 10];

    let double_vec = new_vec
        .iter()
        .inspect(|first_item| {
            println!("The item is: {}", first_item);
            match **first_item % 2 { // 第一個元素是 &&i32 所以我們用 **
                0 => println!("It is even."),
                _ => println!("It is odd."),
            }
            println!("In binary it is {:b}.", first_item);
        })
        .map(|x| x * 2)
        .collect::<Vec<i32>>();
}

印出:

The item is: 8
It is even.
In binary it is 1000.
The item is: 9
It is odd.
In binary it is 1001.
The item is: 10
It is even.
In binary it is 1010.