Rustの dbg! はどうやって動いてるか

デバッグしてますか?

私はよくやってます。

# [dbg!](https://doc.rust-lang.org/std/macro.dbg.html)

これがないと仕事になりません。

```rust

let a = 2;
let b = dbg!(a * 2) + 1;

assert_eq!(b, 5);
```

とか


```rust
fn factorial(n: u32) -> u32 {
    if dbg!(n <= 1) {
        dbg!(1)
    } else {
        dbg!(n * factorial(n - 1))
    }
}
```

みたいに処理の途中に挟んでも動く。

# どう動いてるのか

他の言語、例えばPythonなんかで、

```python
fruits = ["apple", "banana", "cherry"]
for x in fruits:
  if print(x == "banana"):
     print(x)
```

とかできないし。なんか後ろで黒魔術的なことをやってるんじゃないだろうか。
と思ってソースを読んでみました

```rust
#[macro_export]
#[stable(feature = "dbg_macro", since = "1.32.0")]
macro_rules! dbg {
    () => {
        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
    };
    ($val:expr) => {
        // Use of `match` here is intentional because it affects the lifetimes
        // of temporaries - https://stackoverflow.com/a/48732525/1063961
        match $val {
            tmp => {
                $crate::eprintln!("[{}:{}] {} = {:#?}",
                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                tmp
            }
        }
    };
    // Trailing comma with single argument is ignored
    ($val:expr,) => { $crate::dbg!($val) };
    ($($val:expr),+ $(,)?) => {
        ($($crate::dbg!($val)),+,)
    };
}

```

意外に短いです・・・
ちょっといじってみます。

[Playgroundへのリンク](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=27fc4267a888575991eacc7395a0d4f1)

```rust
macro_rules! my_dbg {
    () => {
        eprintln!("[{}:{}]", file!(), line!());
    };
    ($val:expr) => {
        match $val {
            tmp => {
                eprintln!(
                    "[{}:{}] {} = {:#?}",
                    file!(),
                    line!(),
                    stringify!($val),
                    &tmp
                );
                tmp
            }
        }
    };
       ($val:expr,) => { my_dbg!($val) };
       ($($val:expr),+ $(,)?) => {
           ($(my_dbg!($val)),+,)
       };
}

fn main() {
    let a = 1234;
    my_dbg!(&a);
}
```

うごいた!!

```
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.45s
     Running `target/debug/playground`
[src/main.rs:27] &a = 1234
```

もうちょっと削ってみると・・・
[Playgroundへのリンク](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fcefa666782fa3409d0ac9e38f7f97e3)

```rust
macro_rules! my_dbg {
    ($val:expr) => {
        match $val {
            tmp => {
                eprintln!(
                    "{:#?}",
                    &tmp
                );
                tmp
            }
        }
    };
}

fn main() {
    let a = 1234;
    my_dbg!(&a);
    
    if my_dbg!(a == 1234) {
        "HI";
    } else {
        "YO";
    };
}

```


動いてる・・・・

```
   Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.47s
     Running `target/debug/playground`
1234
true
```

# 結論

なるほどこういうことか・・・・

```rust
fn main() {
    let a = 1234;

    if {
        match a == 1234 {
            tmp => {
                eprintln!("{:#?}", &tmp);
                tmp
            }
        }
    } {
        "HI";
    } else {
        "YO";
    };
}

```