kdnakt blog

hello there.

Rust dojo第12回を開催した

第12回です。

前回はこちら。

kdnakt.hatenablog.com

 

 

[第12回の様子]

2021/09/29に第12回を開催した。

 

内容としてはRust By Example 日本語版の「3.2.2. C言語ライクな列挙型」、「3.2.3. テストケース: 連結リスト」に取り組んだ。

 

参加者は全部で8人くらいのはず。もうちょっといたかも?

今回も初ドライバのメンバーが担当!

 

Slackでの書き込みはごくわずか...。

 

[学んだこと]

enum Number {
    Zero,
    One,
    Two,
}

// i32にキャスト
println!("zero is {}", Number::Zero as i32); // zero is 0 
println!("one is {}", Number::One as i32);   // one is 1
  • 任意の値をセットすることもできる
enum Color {
    Red = 0xff0000,
    Green = 0x00ff00,
    Blue = 0x0000ff,
}

// 6桁のゼロ埋め16進数表記
println!("roses are #{:06x}", Color::Red as i32);    // roses are #ff0000
println!("violets are #{:06x}", Color::Blue as i32); // violets are #0000ff
  • じゃあ上の2つを組み合わせたらどうなる?
enum Number {
    Zero,
    Ten = 10,
    Nazo, // 11になった
}

println!("zero is {}", Number::Zero as i32); // zero is 0 
println!("ten is {}", Number::Ten as i32);   // ten is 10
println!("nazo is {}", Number::Nazo as i32); // nazo is 11
// enumは連結リストを作るのに向いているらしい
// なんかもうちょいほかにないのか...
enum List {
    Cons(u32, Box<List>), // Boxはなんか入れ物だとおもっておけばいいらしい。
    Nil,
}
  • 列挙型にもメソッドを実装できる
impl List {
    // 空リストを作成するコンストラクタ的なメソッド。
    // 慣例的にnewと名付けることが多いらしい。
    fn new() -> List {
        Nil
    }

    // リストを受け取り、その始端に新しい要素を付加したものを返す関数。
    fn prepend(self, elem: u32) -> List {
        // selfの所有権はConsに移る
        // オリジナルのインスタンス(self)は呼び出せなくなる
        // 戻り値を受け取って処理を続ける必要がある
        Cons(elem, Box::new(self))
    }

    // 長さを返す。
    // メソッド呼び出し後、所有権を移さないために実体のselfではなく参照
    fn len(&self) -> u32 {
        match *self {
            // *selfで実体を借用しているので、destructしたtailの所有権を取れない
            // ref修飾子で参照を取得
            Cons(_, ref tail) => 1 + tail.len(),
            // 空リストならば長さは0
            Nil => 0
        }
    }
    
    // heap上の文字列として表したものを返すメソッド。
    // rustの文字列は難しいと聞いているのであまり深入りしない...
    fn stringify(&self) -> String {
        match *self {
            Cons(head, ref tail) => {
                // `format!`はheap上の文字列を返す。
                format!("{}, {}", head, tail.stringify())
            },
            Nil => {
                format!("Nil")
            },
        }
    }
}
  • これを呼び出すコードを以下のようになる
fn main() {
    // 空の連結リストを作成
    let mut list = List::new();

    // 要素を追加
    list = list.prepend(1);
    list = list.prepend(2);
    list = list.prepend(3);

    // 追加後の状態を表示
    println!("linked list has length: {}", list.len()); // 3
    println!("{}", list.stringify()); // 3, 2, 1, Nil
    
    // mut修飾子を使わない場合こう書く
    let list = List::new();
    let list = list.prepend(1);
    let list = list.prepend(2);
    let list = list.prepend(3);
    println!("linked list has length: {}", list.len()); // 3
    println!("{}", list.stringify()); // 3, 2, 1, Nil
}
  • mutを使うのもletを毎回つけるのもどっちもなんか違和感があるね、という話になった。

 

[まとめ]

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

enumで連結リストを作れたぞ!

 

今週のプルリクエストはこちら。

github.com