Rustでよく使う標準トレイト一覧:Display・Debug・Clone・Iteratorなど

スポンサーリンク

Rustでよく使う標準トレイト一覧:Display・Debug・Clone・Iteratorなど

はじめに

Rustの標準ライブラリには多くのトレイトが用意されています。コードを書いていると #[derive(Debug)]impl Display for といった記述を頻繁に見かけます。

この記事ではよく使う標準トレイトを用途別にまとめます。トレイトの基本的な書き方は「Rustのトレイト入門:実装方法を基礎から解説」を参照してください。


表示・デバッグ系

Debug

デバッグ用の出力({:?})を有効にします。ほぼすべての型で derive できます。

#[derive(Debug)]
struct Point {
    x: i32,
    y: i32,
}

let p = Point { x: 1, y: 2 };
println!("{:?}", p);   // Point { x: 1, y: 2 }
println!("{:#?}", p);  // 整形表示

Display

ユーザー向けの出力({})を有効にします。derive は使えないので手動で実装します。

use std::fmt;

struct Point {
    x: i32,
    y: i32,
}

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

let p = Point { x: 1, y: 2 };
println!("{}", p);  // (1, 2)

コピー・クローン系

Clone

値を明示的に複製します。clone() メソッドを呼び出すことで複製できます。

#[derive(Clone, Debug)]
struct Config {
    name: String,
}

let a = Config { name: "config".to_string() };
let b = a.clone();
println!("{:?}", b);  // Config { name: "config" }

Copy

代入時に自動的にコピーされます(clone() 不要)。スタックに乗る小さな型に使います。

#[derive(Copy, Clone, Debug)]
struct Point {
    x: i32,
    y: i32,
}

let a = Point { x: 1, y: 2 };
let b = a;  // コピーされる(aも引き続き使える)
println!("{:?}", a);  // OK

StringVec のようにヒープを持つ型には Copy は実装できません。


比較系

PartialEq / Eq

==!= を使えるようにします。

#[derive(Debug, PartialEq)]
struct Point {
    x: i32,
    y: i32,
}

let a = Point { x: 1, y: 2 };
let b = Point { x: 1, y: 2 };
println!("{}", a == b);  // true

EqPartialEq の完全版(すべての値同士が比較可能なことを保証)。多くの場合は両方 derive します。

#[derive(Debug, PartialEq, Eq)]
struct Id(u32);

PartialOrd / Ord

<, >, <=, >= を使えるようにします。ソートに必要です。

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Score(u32);

let mut scores = vec![Score(80), Score(60), Score(90)];
scores.sort();
println!("{:?}", scores);  // [Score(60), Score(80), Score(90)]

デフォルト値系

Default

型のデフォルト値を返します。

#[derive(Debug, Default)]
struct Config {
    width: u32,
    height: u32,
    title: String,
}

let c = Config::default();
println!("{:?}", c);  // Config { width: 0, height: 0, title: "" }

一部のフィールドだけカスタム値にしたいときに便利です。

let c = Config {
    title: "マイアプリ".to_string(),
    ..Default::default()
};

イテレータ系

Iterator

for ループや mapfilter などのメソッドを使えるようにします。next() を実装するだけで多数のメソッドが自動的に使えます。

struct Counter {
    count: u32,
    max: u32,
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<u32> {
        if self.count < self.max {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

let counter = Counter { count: 0, max: 3 };
let v: Vec<u32> = counter.collect();
println!("{:?}", v);  // [1, 2, 3]

From / Into

型変換を定義します。From を実装すると Into が自動で使えます。

struct Wrapper(i32);

impl From<i32> for Wrapper {
    fn from(val: i32) -> Self {
        Wrapper(val)
    }
}

let w = Wrapper::from(42);
let w: Wrapper = 42.into();  // Into も自動で使える

まとめ

トレイト 用途 derive可否
Debug {:?} での出力
Display {} での出力 ❌(手動実装)
Clone .clone() で複製
Copy 代入時に自動コピー
PartialEq / Eq == / != 比較
PartialOrd / Ord 大小比較・ソート
Default デフォルト値
Iterator イテレータ操作 ❌(手動実装)
From / Into 型変換 ❌(手動実装)