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
String や Vec のようにヒープを持つ型には 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
Eq は PartialEq の完全版(すべての値同士が比較可能なことを保証)。多くの場合は両方 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 ループや map・filter などのメソッドを使えるようにします。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 |
型変換 | ❌(手動実装) |