dbg_if
dbg! in the loop without terminal woes.
Summary
The macro [dbg_once!] only prints its value the first time.
use dbg_once;
for i in 0..10
The macro [dbg_if_ne!] only prints changed values.
use dbg_if_ne;
f; // Outputs: [src/lib.rs:58:9] x = 1
f; // No output.
f; // Outputs: [src/lib.rs:58:9] x = 2
The macro [dbg_if_hash_ne!] only prints on changed hash values.
use dbg_if_hash_ne;
let mut s: String = "hello".into;
f; // Outputs: [src/lib.rs:37:9] x = "hello"
f; // No output.
s.push;
f; // Outputs: [src/lib.rs:37:9] x = "hello!"
The sister macros [once!], [was_ne!], and [was_hash_ne!] return true instead
of printing.
Finally the macro [dbg_if] provides a kind of drop-in replacment for
dbg if that is your preference.
use dbg_if as dbg;
let mut x: u8 = 0;
x = f;
// Outputs:
// [src/lib.rs:10:9] x + 1 = 1
// [src/lib.rs:11:9] x + 2 = 2
// [src/lib.rs:12:9] x + 3 = 3
// [src/lib.rs:13:9] x + 4 = 4
x = f;
// Outputs:
// [src/lib.rs:10:9] x + 1 = 1
Feature "float"
If the feature "float" is enabled, these macros are available:
- [
abs_diff_ne_args!] acceptsepsilonargument, - [
relative_ne_args!] acceptsepsilonandrelative_maxarguments, - and [
ulps_ne_args!] acceptsepsilonandulps_maxarguments.
These can be given as the third argument to [was_ne!] or [dbg_if_ne!]. See
the [approx] crate for more details.
Goals
- Ease debugging inspection without resorting to a debugger.
Motivation
assert_eq!;
The dbg! macro is great. It's like being able to add a probe right into your
code without disturbing everything since it works on expressions and lets them
"pass thru." For straight shot code, it is perfect.
But Not In Loops
[src/main.rs:59:18] x = 1
[src/main.rs:59:18] x = 1
[src/main.rs:59:18] x = 1
...^C
For code in tight loops, however, dbg! leaves something to be desired. The
terminal screams, "x = 1" again and again. There has got to be a better way.
Can We Do Better?
Yes! Let's take note of the value at the call site—with a static atomic
variable—and instead of spamming the terminal with the same information, let's
only emit information when it has changed with [dbg_if_ne!].
use dbg_if_ne;
f; // Outputs: [src/main.rs:59:18] x = 1
But I Have Non-Atomic Values?
That's fine. Can they be hashed? Because hashes can be stored in an AtomicU64
at the call site. Just use [dbg_if_hash_ne!].
Tests
Some tests require a particular setup in order to run successfully. A couple of
aliases have been placed in .cargo/config.toml to run these tests.
cargo testruns thewas*tests.cargo test-outputruns above and thedbg*tests which verify its output on stdout.cargo test-allruns above and the float features.
If you see errors that say, "Redirect already exists," that's because some tests
check the stdout and cannot be run multi-threaded. Use cargo test-output to
run them with the right arguments.
License
This crate is licensed, at your option, under either
- the Apache License, Version 2.0 or
- the MIT license.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Acknowledgments
Thank you to Philipp Oppermann for his crate
once. I initially thought I'd only
write dbg_once! and submit a PR. But once I got going I realized dbg_if_ne!
would be useful too and these are all require std; once is a no_std crate.
So dbg_if is inspired and informed by once but it actually doesn't share
any code with once.