Is there a way to write:
dbg!("some header text: {}", &my_var);
I found debug_macros
crate but not maintained anymore.
Is there a way to write:
dbg!("some header text: {}", &my_var);
I found debug_macros
crate but not maintained anymore.
No there is not, you can use the println
macro instead. If you want file and line numbers then you can use the file
, line
, and column
macros to get that info.
Thanks!
Alternatively, you could define your own macro based on dbg!
. Like so:
macro_rules! dbg_msg {
($val:expr) => {
match $val {
tmp => {
eprintln!("[{}:{}] {} = {:#?}",
file!(), line!(), stringify!($val), &tmp);
tmp
}
}
};
($tag:expr, $val:expr $(,)?) => {
match $val {
tmp => {
eprintln!("[{}:{}] ({:#?}) {} = {:#?}",
file!(), line!(), $tag, stringify!($val), &tmp);
tmp
}
}
}
}
The awkward match statement is part of the standard library implementation, so I just followed it.
Silly approach that you probably don't want to do:
dbg!({ "some header text"; &my_var });
[src/main.rs:3] { "some header text"; &my_var } = 4
It's like that because of the lifetimes of temporaries, IIRC. match A { x => B }
is Rust's version of an ML let x = A in B
.
A variant on @OptimisticPeach suggestion (is more flexible regarding the positioning of different items)
macro_rules! dbgf {
(
$fmt:expr, $val:expr $(,)?
) => (
match $val {
| tmp => {
eprintln!(
concat!("[{}:{}] ", $fmt),
file!(),
line!(),
format_args!(
"{} = {:?}",
stringify!($val),
tmp,
),
);
tmp
},
}
);
(
$val:expr $(,)?
) => (
dbgf!("{}", $val)
);
}
Why this is not in std
???
Probably because one of the ideas with dbg!
was to have it allow multiple arguments and treat them as a tuple:
let (a, b) = dbg!(1, 2);
Personally I think passing a tuple into dbg!
is easy enough and gives a decent enough output and having it support an optional format string would be a better use of extra arguments (although I'd personally design it a bit differently to the one @Yandros implemented).
I agree, the implementation I suggested targeted adding contextual text, but I personally find it more useful to cutomize the formatting:
macro_rules! dbgf {
(
$fmt:expr, $expr:expr $(,)?
) => (
match $expr {
| tmp => {
eprintln!(
concat!("[{}:{}:{}] {} = ", $fmt),
file!(),
line!(),
column!(),
stringify!($expr),
tmp,
);
tmp
},
}
);
(
$expr:expr $(,)?
) => (
dbgf!("{:#?}", $expr) // default formatting is {:#?} as with dbg!
);
}
Now, the question is whether we can have both contextual text, and custom formatting, and the answer is yes, but it requires a helper struct:
use ::std::fmt;
// #[macro_export]
macro_rules! dbgf {
(
$fmt:expr, $expr:expr $(,)?
) => (
match $expr {
| tmp => {
eprintln!(
concat!("[{}:{}:{}] ", $fmt),
file!(),
line!(),
column!(),
$crate::WithPrefix {
prefix: concat!(stringify!($expr), " = "),
value: &tmp,
},
);
tmp
},
}
);
(
$expr:expr $(,)?
) => (
dbgf!("{:#?}", $expr) // default formatting
);
}
// #[doc(hidden)] pub
struct WithPrefix<'prefix, T> {
prefix: &'prefix str,
value: T,
}
macro_rules! impl_fmtTraits_for_WithPrefix {(
$( $Trait:ident ),* $(,)?
) => (
$(
impl<T : fmt::$Trait> fmt::$Trait for WithPrefix<'_, T> {
fn fmt (
self: &'_ Self,
stream: &'_ mut fmt::Formatter<'_>,
) -> fmt::Result
{
stream.write_str(self.prefix)?;
self.value.fmt(stream)
}
}
)*
)}
impl_fmtTraits_for_WithPrefix! {
Display, Debug, Octal, LowerHex, UpperHex, Pointer, Binary, LowerExp, UpperExp,
}
EDIT: Fixed using {:?}
as the default formatter instead of ::std::dbg!
's {:#?}
, as @Nemo157 pointed out
dbg!
actually uses {:#?}
which is one of the main reasons I'd like to be able to override it to {:?}
.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.