第12回です。
前回はこちら。
[第12回の様子]
2021/09/29に第12回を開催した。
内容としてはRust By Example 日本語版の「3.2.2. C言語ライクな列挙型」、「3.2.3. テストケース: 連結リスト」に取り組んだ。
参加者は全部で8人くらいのはず。もうちょっといたかも?
今回も初ドライバのメンバーが担当!
Slackでの書き込みはごくわずか...。
[学んだこと]
- 3.2.2. C言語ライクな列挙型
- Unitの列挙型は0始まりの値が入る
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で連結リストを作れたぞ!
今週のプルリクエストはこちら。