LoginSignup
4
6

More than 3 years have passed since last update.

RustのDebugとDisplay

Last updated at Posted at 2020-01-31

概要

Rustでは簡単にprintするためのDebugときれいにprintするためのDisplayという2つのtraitがあります。
初心者ながら、これらを調べるのに苦労したので、書き残しておきます。

簡単に、次のような単方向リストで例示します。メソッドの実装は割愛します。

#[derive(Debug)]
struct List<T> {
    head: Option<Box<Node<T>>>,
}
#[derive(Debug)]
struct Node<T> {
    value: T,
    next: Option<Box<Node<T>>>,
}

Debugの場合

上のように#[derive(Debug)]とすることにより簡単に実装されます。使うときは{:?}とすることに注意!
また、dbg!マクロも便利です(eprintln!と同じくstderrに出力され、何行目の出力かも出る。詳しくはRustのdbg!マクロについて)。

let mut list = List::new();
for i in &[1, 2, 3] {
    list.push_back(i);
}
println!("{:?}", &list); // 表示結果 List { head: Some(Node { value: 1, next: Some(Node { value: 2, next: Some(Node { value: 3, next: None }) }) }) 
dbg!(&list); // これでもよい

Displayの場合

次のように実装してみます。結構やってみると難しいです。Nodeに入っている値がDisplayを実装していないと難しいので<T: fmt::Display>としています。

use std::fmt;
impl<T: fmt::Display> fmt::Display for List<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut node = match self.head {
            None => return write!(f, "has no nodes"),
            Some(ref b) => {
                let _ = write!(f, "{} ", &b.value); // 結果を明示的に捨てないとwarnが出る
                b.as_ref()
            }
        };
        while let Some(ref b) = node.next {
            let _ = write!(f, "{} ", &b.value);
            node = b.as_ref();
        }
        write!(f, "") // 上で結果を捨てないでそれを返すほうが自然? Stringを伸ばしていって最後にwrite!したほうがいい?
    }
}

とすると

let mut list = List::new();
println!("{}", &list); // 表示結果 has no nodes
for i in &[1, 2, 3] {
    list.push_back(i);
}
println!("{}", &list); // 表示結果 1 2 3 

となります。

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6