第7回です。
前回はこちら。
[第7回の様子]
2021/08/25に第7回を開催した。
今回はちょっと遅れて、無事参加できた。5分遅刻した結果先に始まっていたけど、みんな自律的に動けていて良い。次は遅刻しないようにしよう(そもそも直前にMTGを入れなければよいのだが...)。
内容としてはRust By Example 日本語版の「2.2. タプル」を読んで手を動かした。
参加者は全部で10人。ひさびさの2桁!なかなか盛況である。
今回も、前回終了時に決めておいたメンバーがドライバーを担当。
今週も開催前後のSlackでのやりとりがたくさん🎉
タプルの制約の話。
所有権難しい...。
手を動かしててエライ。
来週はぜひぜひ。
[学んだこと]
- 2.2. タプル
- タプルは値の集合で、()で生成する
let tuple = (10, true);
- 関数が複数の値を返すときに使うらしい
- 様々な型をまとめられる:まとめた値にはインデックスでアクセスできる
let long_tuple = (1u8, 2u16, 3u32, 4u64, -1i8, -2i16, -3i32, -4i64, 0.1f32, 0.2f64, 'a', true); println!("long tuple first value: {}", long_tuple.0); println!("long tuple second value: {}", long_tuple.1);
- タプルのタプルも定義できる
let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);
- タプルの要素は12個までならprintlnで出力できる:13個だとコンパイルエラーになる(printlnしなければ利用可能)
let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); println!("too long tuple: {:?}", too_long_tuple.4); // 上記コードは以下のコンパイルエラー error[E0277]: `({integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer})` doesn't implement `Debug` --> src/main.rs:39:38 | 39 | println!("too long tuple: {:?}", too_long_tuple); | ^^^^^^^^^^^^^^ `({integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer})` cannot be formatted using `{:?}` because it doesn't implement `Debug` | = help: the trait `Debug` is not implemented for `({integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer}, {integer})` = note: required by `std::fmt::Debug::fmt` = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
- タプルは関数の引数や戻り値に利用できる
fn reverse(pair: (i32, bool)) -> (bool, i32) { // 分解して別の変数に代入できる let (integer, boolean) = pair; // 別のタプルを生成する (boolean, integer) } let pair = (1, true); println!("pair is {:?}", pair); // pair is (1, true) println!("the reversed pair is {:?}", reverse(pair)); // the reversed pair is (true, 1)
- 1要素だけのタプルをつくる場合にはカンマを忘れずに
println!("one element tuple: {:?}", (5u32,)); // one element tuple: (5,) println!("just an integer: {:?}", (5u32)); // just an integer: 5
- 演習1:Matrix構造体にいい感じの
fmt::Display
トレイトを実装せよ
#[derive(Debug)] struct Matrix(f32, f32, f32, f32); impl fmt::Display for Matrix { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "( {} {} )\n( {} {} )", self.0, self.1, self.2, self.3) } } let matrix = Matrix(1.1, 1.2, 2.1, 2.2); println!("{:}", matrix); // ( 1.1 1.2 ) // ( 2.1 2.2 )
- 演習2:Matrix構造体の要素を入れ替える
transpose()
関数を実装せよ - 最初の実装はこんなかんじ
#[derive(Debug)] struct Matrix(f32, f32, f32, f32); fn transpose(matrix: Matrix) -> Matrix { Matrix(matrix.0, matrix.2, matrix.1, matrix.3) } let matrix = Matrix(1.1, 1.2, 2.1, 2.2); println!("Matrix:\n{}", matrix); // Matrix: // ( 1.1 1.2 ) // ( 2.1 2.2 ) println!("Transpose:\n{}", transpose(matrix)); // Transpose: // ( 1.1 2.1 ) // ( 1.2 2.2 )
- これだけだと、次のようにtrasnposeを呼び出した後の変数matrixを再利用できなくなってしまう
let matrix = Matrix(1.1, 1.2, 2.1, 2.2); println!("Matrix:\n{}", matrix); println!("Transpose:\n{}", transpose(matrix)); println!("Matrix Again:\n{}", matrix); // 以下のコンパイルエラー error[E0382]: borrow of moved value: `matrix` --> src/main.rs:79:35 | 73 | let matrix = Matrix(1.1, 1.2, 2.1, 2.2); | ------ move occurs because `matrix` has type `Matrix`, which does not implement the `Copy` trait ... 78 | println!("Transpose:\n{}", transpose(matrix)); | ------ value moved here 79 | println!("Matrix Again:\n{}", matrix); | ^^^^^^ value borrowed here after move
- rustにはオブジェクトの所有権があり、他の関数に渡してしまうとその後利用できなくなる
- 解決策は以下のいずれか
- Matrix構造体に
#[derive(Debug, Copy, Clone)]
としてCopyトレイトとCloneトレイトを追加する - transpose関数の引数で参照を渡すようにする
fn transpose(matrix: &Matrix) -> Matrix { Matrix(matrix.0, matrix.2, matrix.1, matrix.3) } println!("Matrix:\n{}", matrix); println!("Transpose:\n{}", transpose(&matrix)); println!("Matrix Again:\n{}", matrix); // 問題なく実行できる
[まとめ]
モブプログラミングスタイルでRust dojoを開催した。
ついに所有権の話がでてきた...!気をつけねば。
今週のプルリクエストはこちら。