Rust dojo第49回を開催した

1週あけての第49回です。前回はこちら。

kdnakt.hatenablog.com

 

 

[第49回の様子]

2022/08/03に第49回を開催した。

 

内容としてはRust By Example 日本語版の16. トレイトの続きで、「16.1. 継承(Derive)」、「16.2. Returning Traits with dyn」に取り組んだ。

 

参加者は自分を入れて5人。ちょっと遅れてもちゃんと参加してくれてありがたい。

 

[学んだこと]

// `Inches`はプリント可能なタプルになる
#[derive(Debug)]
struct Inches(i32);

fn main() {
    let foot = Inches(12);

    println!("One foot equals {:?}", foot);
    // One foot equals Inches(12)
}
  • PartialEqトレイトを使うと比較演算が可能になる
// `Centimeters`は比較可能なタプル
#[derive(PartialEq, PartialOrd)]
struct Centimeters(f64);

#[derive(Debug)]
struct Inches(i32);

impl Inches {
    fn to_centimeters(&self) -> Centimeters {
        let &Inches(inches) = self;

        Centimeters(inches as f64 * 2.54)
    }
}

fn main() {
    let foot = Inches(12);

    let meter = Centimeters(100.0);

    let cmp =
        if foot.to_centimeters() < meter {
            "smaller"
        } else {
            "bigger"
        };

    println!("One foot is {} than one meter.", cmp);}
    // smaller
}
  • Defaultトレイトというのもあるらしい
    • 自動的にデフォルト値が入った構造体が作れるのは便利かも。
#[derive(Default, Debug)]
struct SomeOptions {
    foo: i32,
    bar: f32,
}

fn main() {
    let options: SomeOptions = Default::default();
    
    println!("{:?}", options);
    // SomeOptions { foo: 0, bar: 0.0 }
}
  • 16.2. Returning Traits with dyn
  • Rustコンパイラはメモリ確保のために、Traitではなく具象型を関数の返り値の型として必要とするらしい
  • なので、Animalトレイトがあった場合、関数の返り値の型にこれをそのまま利用することはできず、ヒープメモリ上のデータを指すBoxを利用して、Box<dyn Animal>のように書く必要がある
// 具象型
struct Sheep {}
struct Cow {}

// トレイト
trait Animal {
    // インスタンスメソッド
    fn noise(&self) -> &'static str;
}

impl Animal for Sheep {
    fn noise(&self) -> &'static str {
        "baaaaah!"
    }
}

impl Animal for Cow {
    fn noise(&self) -> &'static str {
        "moooooo!"
    }
}

// Animalトレイトを実装した型へのポインタを返す関数
fn random_animal(random_number: f64) -> Box<dyn Animal> {
    if random_number < 0.5 {
        Box::new(Sheep {})
    } else {
        Box::new(Cow {})
    }
}

fn main() {
    let random_number = 0.234;
    let animal = random_animal(random_number);
    
    // Boxでラップした型のメソッドを直接呼び出せる
    println!("You've randomly chosen an animal, and it says {}", animal.noise());
    // baaaaah!(Sheepが返る)
}
  • このへんは以前Rustでインタプリタ言語を実装しようとしてハマった部分...苦手意識が強いのでじっくり理解していきたいところ。

 

[まとめ]

モブプログラミングスタイルでRust dojoを開催した。

トレイトの基本を押さえた。この辺はまだ比較的簡単...。

 

プルリクエストはそのうち追記予定。

[2022/08/10追記]

github.com