気になったのでメモ。
-
2017-10-06T15:05 - リンク先の修正 +
format!()の説明を追加
Rust におけるフォーマット出力(おさらい)
Rust では、フォーマット付きの出力・文字列変換を実現するためにいくつかのマクロが提供されている。
-
print!(),println!()- 標準出力への出力 -
eprint!(),eprintln!()- 標準エラー出力への出力 -
write!(),writeln!()-core::io::Writeまたはcore::fmt::Writeを実装した型(ファイルなど)への出力 -
format!()-Stringへの変換 -
format_args!()-Argumentsの生成 これらのうち、format_args!()はコンパイラ組み込みで、それ以外は通常の Rust のマクロとして定義されている。例えば、write!(),format!()はそれぞれ次のように定義されている。
macro_rules! write {
($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
}macro_rules! format {
($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
} write!() 内で呼び出されているメソッド $dst.write_fmt(args) は core::fmt::Write と std::io::Write が該当し、使用する側のトレイトを予めインポートしておく必要がある。
両者の違いは戻り値のエラー型に現れ、簡単に言うと fmt::Write の方はフォーマット関連のエラーのみを扱うのに対し io::Write はそれ以外の(IO関連の)エラーを返す可能性を持っている。まぁ通常は io::Write の方を使うことがほとんどだと思うが。
-
core::fmt::Write::write_fmt()-core::fmt::Result -
std::io::Write::write_fmt()-io::Result<()>
エラー処理回りを除けば、両トレイトのデフォルト実装では最終的に core::fmt::write(f, args) を呼び出し、指定されたフォーマットで出力が実行される。
一方 format!() の方だが、これは内部で空 String を用意して write_fmt() を呼んでいるだけである。
pub fn format(args: Arguments) -> string::String {
let capacity = args.estimated_capacity();
let mut output = string::String::with_capacity(capacity);
output.write_fmt(args)
.expect("a formatting trait implementation returned an error");
output
}おわりに
core::fmt::write() と format_args!() の挙動がわかれば文字列のフォーマット周りの理解は出来そう。
疲れたので今回はここまで。次回は format_args!() と core::fmt::Arguments の定義回りを見たい。
TODO:
-
core::fmt::Argumentsの説明 -
format_args!()の定義と使い方 -
core::fmt::write()の中身を見る