よこなのへたのよこずき

noteもよろしくね

DisplayトレイトとDebugトレイト、使い方と表示 #Rust

... doesn't implement Display (required by ...) って言われているコードがいたのでこの記事を書いてみることにした

↑スクショではBuildErrorという型の中身を出力すべくpanic!("{}", build_error)*1相当のことをしているのだけど、"{}"を使えるのはDisplayトレイトを実装した型のみなのでエラーが出ている。ということで、Displayの実装についてコードで確認してみよう


nameというフィールドのみ持ったPersonというストラクトの内容を標準出力してみる

#[derive(Debug)] // Debugを使うにはこれを追加するだけ
pub struct Person {
    name: String,
}

// Displayは次のようにトレイトを実装する
impl Display for Person {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "The name of this person is {}", &self.name)
    }
}

fn main() {
    let person = Person { name: "はなこ".to_string() };
    println!("{:?}", person); // Debugトレイトの実装を使う
    println!("{}", person); // Displayトレイトの実装を使う
}

上記の実行結果はこうなる

Person { name: "はなこ" }
The name of this person is はなこ
  • Debugはデフォルト実装があるため、アノテーションを付けるとすぐに使える。デバッグを楽にするのが目的なので中身の詳細をそのまま表示する。publicな型であれば実装しておくのが基本となる
  • Displayにはデフォルト実装がなく、必ず自ら実装する必要がある。必要な型にのみ実装し、出力したい文字列のフォーマットを実現する

ちなみにDebug を使ったときに {:?}{:#?}*2で出力するけど、このハテナの意味は次のページに書いてある。

doc.rust-lang.org

nothing ⇒ Display
? ⇒ Debug
x? ⇒ Debug with lower-case hexadecimal integers
X? ⇒ Debug with upper-case hexadecimal integers
o ⇒ Octal
x ⇒ LowerHex
X ⇒ UpperHex
p ⇒ Pointer
b ⇒ Binary
e ⇒ LowerExp
E ⇒ UpperExp

という風にあるトレイトを実装した型をフォーマットしたい時にどう書くべきかの対応表があって便利!

*1:panic!は内部的にformat!を使っている

*2:#はpretty-printしたいときに付ける。ストラクトとか配列がちょっと綺麗に表示される