デバッグ

std::fmtのフォーマット用トレイトを使用したい型は、プリント可能である用に実装されている必要があります。stdライブラリの型のように自動でプリント可能なものもありますが、他はすべて 手動で実装する必要があります。

fmt::Debugというトレイトはこれを簡略化します。 すべての 型はfmt::Debugの実装をderive、(すなわち自動で作成)することができるためです。 fmt::Displayの場合はやはり手動で実装しなくてはなりません。


#![allow(unused)]
fn main() {
// This structure cannot be printed either with `fmt::Display` or
// with `fmt::Debug`.
// この構造体は`fmt::Display`、`fmt::Debug`のいずれによっても
// プリントすることができません。
struct UnPrintable(i32);

// The `derive` attribute automatically creates the implementation
// required to make this `struct` printable with `fmt::Debug`.
// `derive`アトリビュートは、
// この構造体を`fmt::Debug`でプリントするための実装を自動で提供します。
#[derive(Debug)]
struct DebugPrintable(i32);
}

stdライブラリの型の場合は、自動的に{:?}によりプリント可能になっています。

// Derive the `fmt::Debug` implementation for `Structure`. `Structure`
// is a structure which contains a single `i32`.
// `Structure`という構造体のための`fmt::Debug`をderiveしています。
// `Structure`は単一の`i32`をメンバに持っています。
#[derive(Debug)]
struct Structure(i32);

// Put a `Structure` inside of the structure `Deep`. Make it printable
// also.
// `Deep`という構造体の中に`Structure`を入れます。
// また、これをプリント可能にしています。
#[derive(Debug)]
struct Deep(Structure);

fn main() {
    // Printing with `{:?}` is similar to with `{}`.
    // `{:?}`によるプリントは `{}`に似ています。
    println!("{:?} months in a year.", 12);
    println!("{1:?} {0:?} is the {actor:?} name.",
             "Slater",
             "Christian",
             actor="actor's");

    // `Structure` is printable!
    // `Structure`はプリント可能です!
    println!("Now {:?} will print!", Structure(3));
    
    // The problem with `derive` is there is no control over how
    // the results look. What if I want this to just show a `7`?
    // `derive`を用いることの問題は、結果がどのように見えるか
    // コントロールする方法がないことです。
    // 出力を`7`だけにするためにはどうしたらよいでしょう?
    println!("Now {:?} will print!", Deep(Structure(7)));
}

fmt::Debugは確実にプリント可能にしてくれるのですが、一方である種の美しさを犠牲にしています。 Rustは{:#?}による「見栄えの良いプリント」も提供します。

#[derive(Debug)]
struct Person<'a> {
    name: &'a str,
    age: u8
}

fn main() {
    let name = "Peter";
    let age = 27;
    let peter = Person { name, age };

    // Pretty print
    println!("{:#?}", peter);
}

手動でfmt::Displayを実装することでプリント結果を思い通りにできます。

参照

アトリビュート, derive, std::fmt, 構造体