【Effective-Rustlings-jp】Day 9：標準トレイトに習熟しよう

# はじめに
こんにちは。細々とプログラミングをしている[sotanengel](https://x.com/sota_eng_prog)です。
この記事は以下の記事の連載です。

https://qiita.com/sotanengel/private/78103dcfe2fa34f8815e


<details>
<summary><strong>他の連載記事</strong> (<em>詳細</em>)</summary>

- [Day 1：型システムを使ってデータ構造を再現しよう](https://qiita.com/sotanengel/private/588a7f7cc03c36fc1adc)
- [Day 2：型システムを用いて共通の挙動を表現しよう](https://qiita.com/sotanengel/private/2a8fc62b6d9f8e916021)
- [Day 3：OptionとResultに対してはmatchを用いずに変換しよう](https://qiita.com/sotanengel/items/b54990dc82d877b9d70d)
- [Day 4：標準のErrorを使おう](https://qiita.com/sotanengel/private/79f683c3d75d09244567)
- [Day 5：型変換を理解しよう](https://qiita.com/sotanengel/private/8cc28c8b6108e5998e23)
- [Day 6：newtypeパターンを活用しよう](https://qiita.com/sotanengel/private/38814f8b5a88aad9eccc)
- [Day 7：複雑な型にはビルダを使おう](https://qiita.com/sotanengel/private/80bc555e95ed56b72f14)
- [Day 8：明示的なループの代わりにイテレータ変換を使用することを検討しよう](https://qiita.com/sotanengel/private/f7f4fc03f0b2dc445bf2)
- [Day 9：標準トレイトに習熟しよう](https://qiita.com/sotanengel/private/24a8ad443fc23e779ccd)
- [Day 10：RIIパターンにはDropトレイトを実装しよう](https://qiita.com/sotanengel/private/a3d1b04f98ea80b8989d)
- [Day 11：ジェネリクスとトレイトオブジェクトのトレードオフを理解しよう](https://qiita.com/sotanengel/private/8e2e88d5619b434c3ada)
- [Day 12：デフォルト実装を用いて、実装しなければならないトレイトメソッドを最小限にしよう](https://qiita.com/sotanengel/private/16b02d32732727eaf66f)
- [Day 13：Don't panic](https://qiita.com/sotanengel/private/aa833ce99c8e8b8eecf2)
- [Day 14：リフレクションを避けよう](https://qiita.com/sotanengel/private/6108b22f6644d4fde997)
- [Day 15：可視範囲を最小化しよう](https://qiita.com/sotanengel/private/4075925e05de50dfac96)
- [Day 16：ワイルドカードインポートを避けよう](https://qiita.com/sotanengel/private/555314f77c8318bb1c45)
- [Day 17：パブリックインターフェースのドキュメントを書こう](https://qiita.com/sotanengel/private/b4e8a11522b253ebb62e)
- [Day 18：分別を持ってマクロを使おう](https://qiita.com/sotanengel/private/a33b5ab66a82a26b4adc)
- [Day 19：Clippyに耳を傾けよう](https://qiita.com/sotanengel/private/b4c161bb87fc9e7e813e)
- [Day 20：ユニットテスト以上のものを書こう](https://qiita.com/sotanengel/private/58fcafaee5418b2b2b16)

</details>

また本記事は[Effective Rust(David Drysdale (著), 中田 秀基 (翻訳))](https://www.oreilly.com/library/view/effective-rust/9781098151393/)を参考に作成されております。とてもいい書籍ですので興味を持った方は、ぜひ読んでみてください！
<div style="text-align: center;">
  <figure>
    <a href="https://www.amazon.co.jp/Effective-Rust-%E2%80%95Rust%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E6%94%B9%E5%96%84%E3%81%97%E3%80%81%E3%82%A8%E3%82%B3%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%92%E6%9C%80%E5%A4%A7%E9%99%90%E3%81%AB%E6%B4%BB%E7%94%A8%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE35%E9%A0%85%E7%9B%AE-David-Drysdale/dp/4814400942"  target="_blank">
      <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1758960/cb1245be-02d6-0c74-8b79-e46288f2ea73.png" alt="商品画像" width="50%">
    </a>
  </figure>
</div>

# 今日の内容
## 概要
Rustに標準で実装されているトレイトを使いこなすことで、
簡潔に必要な機能を実装しましょう。

## Cloneを適切に実装しよう。
### 問([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/exercises/10_traits_Familiarize_yourself_with_standard_traits/1_clone.rs))
Cloneを使うことである変数の内容をコピーしましょう。
またどのような場合にコピーすべきでないか考えてみましょう。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

```rust
// TODO: Cloneを実装して、main関数が動くようにしましょう。
#[derive(Debug)]
struct User {
    name: String,
    age: u32,
}

// TODO: この構造体がCloneを実装すべきかどうか考えてみましょう。
#[derive(Debug)]
struct SecretKey {
    key: Vec<u8>,
}

fn main() {
    let user1 = User {
        name: String::from("Alice"),
        age: 30,
    };

    let user2 = user1;

    println!("{:?}", user1);
    println!("{:?}", user2);

    let secret_key = SecretKey {
        key: vec![1, 2, 3, 4, 5],
    };
    println!("{:?}", secret_key);
}
```

</details>

### 解答([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/solutions/10_traits_Familiarize_yourself_with_standard_traits/1_clone.rs))
deriveを使えば簡単にCloneを実装できます。
また情報の管理を厳格にすべき構造体などについてはCloneの実装をよく検討すべきです。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

```rust
#[derive(Debug, Clone)]
#[allow(dead_code)]
struct User {
    name: String,
    age: u32,
}

// 秘密鍵を保持する構造体
// 意図しない場所でコピーを作成して、カギの流出を防ぐためにCloneトレイトは実装しない方が良い
#[derive(Debug)]
#[allow(dead_code)]
struct SecretKey {
    key: Vec<u8>,
}

fn main() {
    let user1 = User {
        name: String::from("Alice"),
        age: 30,
    };

    let user2 = user1.clone();

    println!("{:?}", user1);
    println!("{:?}", user2);

    let secret_key = SecretKey {
        key: vec![1, 2, 3, 4, 5],
    };
    println!("{:?}", secret_key);
}
```

</details>

## Copyを実装しましょう。
### 問([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/exercises/10_traits_Familiarize_yourself_with_standard_traits/2_copy.rs))
PointにCopyを実装しましょう。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

```rust
// TODO: この構造体にCopyを実装しましょう。
#[derive(Debug)]
#[allow(dead_code)]
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p1 = Point { x: 10, y: 20 };
    let p2 = p1; // p1の値がp2にコピーされる（ムーブではなくコピー）

    // TODO: Point構造体がCopyを実装した時に、以下のコードはどのように書き直すべきでしょうか？
    let p3 = p1.clone();

    println!("p1: {:?}", p1);
    println!("p2: {:?}", p2);
    println!("p2: {:?}", p3);
}
```

</details>

### 解答([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/solutions/10_traits_Familiarize_yourself_with_standard_traits/2_copy.rs))
コード参照。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

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

fn main() {
    let p1 = Point { x: 10, y: 20 };
    let p2 = p1; // p1の値がp2にコピーされる（ムーブではなくコピー）

    // CopyトレイトはCloneトレイトに制約を持つのでcloneを使うことができるが、
    // ビット単位のコピーを作成する方が方が速いため、そのまま記載した方が良い。
    let p3 = p1;

    println!("p1: {:?}", p1);
    println!("p2: {:?}", p2);
    println!("p2: {:?}", p3);
}
```

</details>

## Defaultを実装しよう
### 問([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/exercises/10_traits_Familiarize_yourself_with_standard_traits/3_default.rs))
構造体にDefaultを実装して、インスタンスの作成を簡潔に記載できるようにしましょう。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

```rust
// TODO: この構造体にDefaultを実装しましょう。
#[derive(Debug)]
#[allow(dead_code)]
struct Point {
    x: i32,
    y: i32,
    z: i32,
}

// TODO: このenumにDefaultを実装しましょう。
#[derive(Debug)]
#[allow(dead_code)]
enum Mode {
    Automatic, // TODO: デフォルト値はこの要素にしてください。
    Manual,
}

fn main() {
    let p1 = Point::default();
    println!("{:?}", p1);

    // TODO: xには10を代入して、それ以外はデフォルト値を入れましょう。
    let p2 = Point {};
    println!("{:?}", p2);

    let mode = Mode::default();
    println!("{:?}", mode);
}
```

</details>

### 解答([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/solutions/10_traits_Familiarize_yourself_with_standard_traits/3_default.rs))
コード参照。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

```rust
#[derive(Debug, Default)]
// i32がDefaultを実装しているため、この記載だけでデフォルト値が設定できます。
#[allow(dead_code)]
struct Point {
    x: i32,
    y: i32,
    z: i32,
}

#[derive(Debug, Default)]
#[allow(dead_code)]
enum Mode {
    #[default]
    Automatic, // デフォルト値にしたい要素の前に記載をすることで簡単に定義ができます。
    Manual,
}

fn main() {
    let p1 = Point::default();
    println!("{:?}", p1); // Point { x: 0, y: 0 , z:0 }

    let p2 = Point {
        x: 10,
        ..Default::default() // デフォルトを実装することで、フィールドの変更したい部分だけを明示的に書くことで初期化が可能になります。
    };
    println!("{:?}", p2); // Point { x: 10, y: 0 , z:0 }

    let mode = Mode::default();
    println!("{:?}", mode); // Automatic
}
```

</details>

## PartialEqを実装して、比較ができるようにしましょう
### 問([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/exercises/10_traits_Familiarize_yourself_with_standard_traits/4_PartialEq.rs))
User構造体を比較できるようにしましょう。
また、NaNの混入が考えられるMeasurement構造体については自分でPartialEqを実装してみましょう。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

```rust
// TODO: この構造体にPartialEqとEqを実装しましょう。
#[derive(Debug)]
struct User {
    id: u32,
    name: String,
}

// TODO: valueがNaN同士の比較であればtrueを返すように自分でPartialEqを実装しましょう。
#[derive(Debug)]
struct Measurement {
    value: f64,
    unit: String,
}

fn main() {
    let u1 = User {
        id: 1,
        name: String::from("Alice"),
    };

    let u2 = User {
        id: 1,
        name: String::from("Alice"),
    };

    let u3 = User {
        id: 2,
        name: String::from("Bob"),
    };

    println!("u1 == u2: {}", u1 == u2); // true
    println!("u1 == u3: {}", u1 == u3); // false

    let m1 = Measurement {
        value: f64::NAN,
        unit: String::from("m"),
    };

    let m2 = Measurement {
        value: f64::NAN,
        unit: String::from("m"),
    };

    println!("m1 == m2: {}", m1 == m2); // true
}
```

</details>

### 解答([リンク](https://github.com/sotanengel/effective-rustlings-jp/blob/20250101/solutions/10_traits_Familiarize_yourself_with_standard_traits/4_PartialEq.rs))
コード参照。

<details>
<summary><strong>コード</strong> (<em>詳細</em>)</summary>

```rust
#[derive(Debug, PartialEq, Eq)]
struct User {
    id: u32,
    name: String,
}

#[derive(Debug)]
struct Measurement {
    value: f64,
    unit: String,
}

// PartialEqの実装
impl PartialEq for Measurement {
    fn eq(&self, other: &Self) -> bool {
        (self.value.is_nan() && other.value.is_nan())  // 両方がNaNならtrue
            || (self.value == other.value)             // それ以外は通常の比較
            && (self.unit == other.unit) // 単位も比較
    }
}

fn main() {
    let u1 = User {
        id: 1,
        name: String::from("Alice"),
    };

    let u2 = User {
        id: 1,
        name: String::from("Alice"),
    };

    let u3 = User {
        id: 2,
        name: String::from("Bob"),
    };

    println!("u1 == u2: {}", u1 == u2); // true
    println!("u1 == u3: {}", u1 == u3); // false

    let m1 = Measurement {
        value: f64::NAN,
        unit: String::from("m"),
    };

    let m2 = Measurement {
        value: f64::NAN,
        unit: String::from("m"),
    };

    println!("m1 == m2: {}", m1 == m2); // true
}
```

</details>

# さいごに

もしも本リポジトリで不備などあれば、リポジトリのissueやPRなどでご指摘いただければと思います。

https://github.com/sotanengel/effective-rustlings-jp/issues