第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で連結リストを作れたぞ!
今週のプルリクエストはこちら。