デバッグしてますか?
私はよくやってます。
dbg!
これがないと仕事になりません。
let a = 2;
let b = dbg!(a * 2) + 1;
assert_eq!(b, 5);
とか
fn factorial(n: u32) -> u32 {
if dbg!(n <= 1) {
dbg!(1)
} else {
dbg!(n * factorial(n - 1))
}
}
みたいに処理の途中に挟んでも動く。
どう動いてるのか
他の言語、例えばPythonなんかで、
fruits = ["apple", "banana", "cherry"]
for x in fruits:
if print(x == "banana"):
print(x)
とかできないし。なんか後ろで黒魔術的なことをやってるんじゃないだろうか。
と思ってソースを読んでみました
#[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)),+,)
};
}
意外に短いです・・・
ちょっといじってみます。
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へのリンク
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
結論
なるほどこういうことか・・・・
fn main() {
let a = 1234;
if {
match a == 1234 {
tmp => {
eprintln!("{:#?}", &tmp);
tmp
}
}
} {
"HI";
} else {
"YO";
};
}