1 个不稳定版本
0.1.2 | 2022年10月22日 |
---|---|
0.1.1 |
|
0.1.0 |
|
#1410 in Rust 模式
17KB
用法
将以下内容添加到您的 Cargo.toml
[dependencies]
printc = "0.1"
示例
#[macro_use] extern crate printc;
fn main() {
let x = 500;
printc!(x);
}
输出
x = 500
问题陈述
为什么要在杂乱的输入(println!
)和杂乱的输出(dbg!
)之间选择?printc!
允许您同时使用干净的输入和输出进行代码调试。
动机、用例
简短动机
如果您想进行调试,通常您必须选择编写冗长的样板代码(println!
)或者拥有需要更多努力才能直观导航的杂乱输出(dbg!
)。从干净的输入生成干净输出的能力,使您更容易分析代码并更快地学习。
长动机
如果我们想调试代码,标准库 提供以下选项
print!
和 eprint!
很少被使用,因为用户可以选择 println!
和 eprintln!
来获取相同的结果,但结构更清晰,更容易区分不同的输出(尽管在某些情况下,print!
和 eprint!
可能更可取)。因此,print!
和 eprint!
不是产生最小样板代码的清洁输出的最佳选择。
println!
和 eprintln!
可以生成干净的输出,但它们要求你在输入中编写冗长的样板代码。
dbg!
可以接受干净的输入,但输出杂乱无章,需要更多的努力来直观地导航。
例如,你可能希望从文档和论坛(如 github)中复制代码示例,并将它们粘贴到你的本地环境中(或 Rust Playground)中,以对其进行实验,更好地理解代码的实际功能。我们将演示 println!
的杂乱输入和 dbg!
的杂乱输出是什么样的,并将它们与 printc!
进行比较。
假设你对 Pinning 不熟悉,并阅读了关于它的 文档页面,你遇到了下面的 代码示例
fn main() {
let mut test1 = Test::new("test1");
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
Test::init(test1_pin.as_mut());
drop(test1_pin);
println!(r#"test1.b points to "test1": {:?}..."#, test1.b);
let mut test2 = Test::new("test2");
mem::swap(&mut test1, &mut test2);
println!("... and now it points nowhere: {:?}", test1.b);
}
use std::pin::Pin;
use std::marker::PhantomPinned;
use std::mem;
#[derive(Debug)]
struct Test {
a: String,
b: *const String,
_marker: PhantomPinned,
}
impl Test {
fn new(txt: &str) -> Self {
Test {
a: String::from(txt),
b: std::ptr::null(),
// This makes our type `!Unpin`
_marker: PhantomPinned,
}
}
fn init<'a>(self: Pin<&'a mut Self>) {
let self_ptr: *const String = &self.a;
let this = unsafe { self.get_unchecked_mut() };
this.b = self_ptr;
}
#[allow(unused)]
fn a<'a>(self: Pin<&'a Self>) -> &'a str {
&self.get_ref().a
}
#[allow(unused)]
fn b<'a>(self: Pin<&'a Self>) -> &'a String {
assert!(!self.b.is_null(), "Test::b called without Test::init being called first");
unsafe { &*(self.b) }
}
}
为了理解代码,你可能会尝试对其进行实验,以用于教育目的。如前所述,println!
和 dbg!
是标准库提供的最佳选项。让我们修改 main()
函数,看看这两种方法各自的运作情况。
println!
方法
杂乱输入
fn main() {
let mut test1 = Test::new("test1");
println!("test1 = {:#?}", test1);
println!();
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
Test::init(test1_pin.as_mut());
drop(test1_pin);
println!("test1 = {:#?}", test1);
println!();
let mut test2 = Test::new("test2");
println!("test1 = {:#?}", test1);
println!();
println!("test2 = {:#?}", test2);
println!();
mem::swap(&mut test1, &mut test2);
println!("test1 = {:#?}", test1);
println!();
println!("test2 = {:#?}", test2);
println!();
}
整洁输出
test1 = Test {
a: "test1",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
test1 = Test {
a: "test1",
b: 0x00007ffd1bdafb68,
_marker: PhantomPinned,
}
test1 = Test {
a: "test1",
b: 0x00007ffd1bdafb68,
_marker: PhantomPinned,
}
test2 = Test {
a: "test2",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
test1 = Test {
a: "test2",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
test2 = Test {
a: "test1",
b: 0x00007ffd1bdafb68,
_marker: PhantomPinned,
}
dbg!
方法
整洁输入
fn main() {
let mut test1 = Test::new("test1");
dbg!(&test1);
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
Test::init(test1_pin.as_mut());
drop(test1_pin);
dbg!(&test1);
let mut test2 = Test::new("test2");
dbg!(&test1, &test2);
mem::swap(&mut test1, &mut test2);
dbg!(&test1, &test2);
}
杂乱输出
[src/main.rs:7] &test1 = Test {
a: "test1",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
[src/main.rs:13] &test1 = Test {
a: "test1",
b: 0x00007ffca10e7650,
_marker: PhantomPinned,
}
[src/main.rs:16] &test1 = Test {
a: "test1",
b: 0x00007ffca10e7650,
_marker: PhantomPinned,
}
[src/main.rs:16] &test2 = Test {
a: "test2",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
[src/main.rs:19] &test1 = Test {
a: "test2",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
[src/main.rs:19] &test2 = Test {
a: "test1",
b: 0x00007ffca10e7650,
_marker: PhantomPinned,
}
printc!
方法
printc!
允许您同时做到输入整洁和输出整洁。
整洁输入
fn main() {
let mut test1 = Test::new("test1");
printc!(test1);
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
Test::init(test1_pin.as_mut());
drop(test1_pin);
printc!(test1);
let mut test2 = Test::new("test2");
printc!(test1, test2);
mem::swap(&mut test1, &mut test2);
printc!(test1, test2);
}
整洁输出
test1 = Test {
a: "test1",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
test1 = Test {
a: "test1",
b: 0x00007ffd1bdafb68,
_marker: PhantomPinned,
}
test1 = Test {
a: "test1",
b: 0x00007ffd1bdafb68,
_marker: PhantomPinned,
}
test2 = Test {
a: "test2",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
test1 = Test {
a: "test2",
b: 0x0000000000000000,
_marker: PhantomPinned,
}
test2 = Test {
a: "test1",
b: 0x00007ffd1bdafb68,
_marker: PhantomPinned,
}