ディスプレイ

fmt::Debugはコンパクトでクリーンであるようには見えませんね。大抵の場合は、アウトプットの見た目をカスタマイズしたほうが好ましいでしょう。これは{}を使用するfmt::Displayを手動で実装することで可能です。

#![allow(unused)] fn main() { // Import (via `use`) the `fmt` module to make it available. // (`use`を使用し、)`fmt`モジュールをインポートします。 use std::fmt; // Define a structure for which `fmt::Display` will be implemented. This is // a tuple struct named `Structure` that contains an `i32`. // `fmt::Display`を実装するための構造体を定義します。 // これは`Structure`という名前に紐付けられた、`i32`を含むタプルです。 struct Structure(i32); // To use the `{}` marker, the trait `fmt::Display` must be implemented // manually for the type. // `{}` というマーカーを使用するためには、 // この型専用の`fmt::Display`というトレイトが実装されていなくてはなりません。 impl fmt::Display for Structure { // This trait requires `fmt` with this exact signature. // このトレイトは`fmt`が想定通りのシグネチャであることを要求します。 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Write strictly the first element into the supplied output // stream: `f`. Returns `fmt::Result` which indicates whether the // operation succeeded or failed. Note that `write!` uses syntax which // is very similar to `println!`. // 厳密に最初の要素を、与えられた出力ストリーム `f` に書き込みます。 // `fmt::Result`を返します。これはオペレーションが成功したか否か // を表します。 // `write!`は`println!`に非常によく似た文法を使用していることに注目。 write!(f, "{}", self.0) } } }

fmt::Displayfmt::Debugより綺麗かもしれませんが、stdライブラリの場合は問題が生じます。曖昧な(ambiguous)タイプはどのように表示すれば良いでしょう? 例えば、stdライブラリがあらゆるVec<T>に対して単一のスタイルを提供していた場合、どのようなスタイルに整形すればよいでしょう?以下の2つのどちらかを選ぶべきでしょうか?

  • Vec<path>: /:/etc:/home/username:/bin:で分割)
  • Vec<number>: 1,2,3,で分割)

答えはNOです。あらゆる型に対して理想的なスタイルなどというものはありませんし、stdライブラリによってそれが提供されているわけでもありません。fmt::DisplayVec<T>のようなジェネリックなコンテナ用に定義されているわけではありませんので、このような場合はfmt::Debugを使用するべきです。

ジェネリック でない コンテナ型の場合は、このような問題は生じませんので問題なくfmt::Displayを実装することができます。

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

fmt::Displayは実装されていますが、fmt::Binaryはされていないので使用できません。 std::fmtはそのようなトレイトが数多くあり、それぞれに独自の実装が必要です。詳しくはstd::fmtを参照してください。

演習

上記の例のアウトプットを確認し、Point2D構造体を参考として、複素数を格納するためのComplex構造体を定義しましょう。うまく行けば以下のように出力されるはずです。

Display: 3.3 + 7.2i Debug: Complex { real: 3.3, imag: 7.2 }

参照

derive, std::fmt, マクロ, struct, trait, use