目次

Rustの勉強[高度なトレイト その1]

(更新: )ぎじゅつ

はじめに

#

NO IMAGEThe Rust Programming Language 日本語版 - The Rust Programming Language 日本語版

を読んでいる。

お勉強

#

NO IMAGE高度なトレイト - The Rust Programming Language 日本語版

高度なトレイトから。

  • 久しぶりに新しい章だから光らせねーと
  • すげーhow toっぽいなー

メモ

#

関連型は、ジェネリクスにより扱う型を指定せずに関数を定義できるという点でジェネリクスに似た概念のように思える可能性があります。では、何故関連型を使用するのでしょうか?

  • 全然わからん
pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}
  • これが
impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        // --snip--
    }
}
  • こう実装される
pub trait Iterator<T> {
    fn next(&mut self) -> Option<T>;
}
  • これでいいんでねって話をしてる

換言すれば、トレイトにジェネリックな引数があると、毎回ジェネリックな型引数の具体的な型を変更してある型に対して複数回実装できるということです。Counterに対してnextメソッドを使用する際に、どのIteratorの実装を使用したいか型注釈をつけなければならないでしょう

  • ????
  • コードで語れ!
  • こういうのはgeminiが得意そうだな
// もしこう定義されていたら...
pub trait GenericIterator<T> {
    fn next(&mut self) -> Option<T>;
}

struct MyCounter {
    count: i32,
}

// 同じ構造体に対して、i32を返すイテレータと
impl GenericIterator<i32> for MyCounter {
    fn next(&mut self) -> Option<i32> {
        Some(self.count)
    }
}

// Stringを返すイテレータを同時に実装できてしまう
impl GenericIterator<String> for MyCounter {
    fn next(&mut self) -> Option<String> {
        Some(self.count.to_string())
    }
}
  • これを関連型で書くと
pub trait Iterator {
    // 関連型:実装時に「一つ」だけ型を決める
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
}

struct MyCounter {
    count: u32,
}

impl Iterator for MyCounter {
    // ここで型を固定する
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;
        if self.count < 3 {
            Some(self.count)
        } else {
            None
        }
    }
}

fn main() {
    let mut counter = MyCounter { count: 0 };

    // 型が一つに決まっているので、推論が完璧に効く
    while let Some(v) = counter.next() {
        println!("{}", v);
    }
}
  • 推論が楽になるのか
  • まぁあんまり使わないほうがいいんだろうな
    • 面倒なほうが隠蔽できないし

まとめ

#
  • なんで?ってなったが記述量を減らすためだった
  • だけどこれって標準のcrateだからいいんだよな
  • crateを作るなら必要かなと感じた