Rust dojo第44回を開催した

第44回です。前回はこちら。

kdnakt.hatenablog.com

 

 

[第44回の様子]

2022/06/22に第44回を開催した。

 

内容としてはRust By Example 日本語版の「15.3.3. refパターン」、「15.4. ライフタイム」、「15.4.1. 明示的アノテーション」に取り組んだ。

 

参加者は自分を入れて4人。継続的に参加してくれる皆様に感謝。

 

[学んだこと]

  • 15.3.3. refパターン
  • 先週まで、借用の方法として&T型を利用してきた
  • 同じようにrefキーワードを利用して借用することもできる
fn main() {
    let c = 'Q';

    // 借用方法2パターン:どちらも結果は同じ
    let ref ref_c1 = c;
    let ref_c2 = &c;

    // アドレスも出力して値が同じだけでなく参照先が同じことも確認
    println!("ref_c1 equals ref_c2: {}, {:p}, {:p}", *ref_c1 == *ref_c2, ref_c1, ref_c2);
    // ref_c1 equals ref_c2: true, 0x7ffc11447c14, 0x7ffc11447c14
}
  • デストラクトする時など、&が使えないときにrefキーワードを利用する
#[derive(Clone, Copy)]
struct Point { x: i32, y: i32 }

fn main() {
    let point = Point { x: 0, y: 0 };

    let _copy_of_x = {
        // xへの参照を取得
        let Point { x: ref ref_to_x, y: _ } = point;

        // コピーを返す
        *ref_to_x
    };
    
    println!("{} {:p}", _copy_of_x, &_copy_of_x);
    // 0 0x7ffd09aaee14
    // コピーなのでアドレスが変わっている
}
  • ミュータブルにrefを取ることもできる
#[derive(Clone, Copy)]
struct Point { x: i32, y: i32 }

fn main() {
    let point = Point { x: 0, y: 0 };
    let mut mutable_point = point;

    {
        // yのミュータブルな参照を取得
        let Point { x: _, y: ref mut mut_ref_to_y } = mutable_point;

        *mut_ref_to_y = 1;
    }

    println!("point is ({}, {})", point.x, point.y); // 0, 0
    println!("mutable_point is ({}, {})", mutable_point.x, mutable_point.y); // 0, 1
}
// aというライフタイムパラメータをもつfoo
// fooのライフタイムはaのライフタイムを超えない
foo<'a>

// a、bというライフタイムパラメータをもつfoo
// fooのライフタイムはaとbのライフタイムを超えない
foo<'a, 'b>
  • 関数の場合、以下のようになる
// `print_refs`は`i32`への参照を2つとる
// 変数は'aと'bというライフタイムを持つ
fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) {
    println!("x is {} and y is {}", x, y);
}

fn main() {
    let (four, nine) = (4, 9);
    
    // 2つの変数の借用(`&`)を関数に渡す
    print_refs(&four, &nine);
    // x is 4 and y is 9
}
  • 引数を取らない関数もライフタイムパラメータをもつことがある
    • その場合、'staticなライフタイムとなる
fn failed_borrow<a>() {
    let _x = 12;

    let y: &'a i32 = &amp_x;
    // &_xのライフタイムはこの関数内に限定される
    // しかしyはライフタイムパラメータ'aをもつ
    // failed_borrowは引数として参照を持たない
    // この場合ライフタイム'aはデフォルトで'staticになる
    // staticはプログラムの開始から終了までのイメージ(違うかも
    // yのライフタイムより&_xのライフタイムの方が短いため代入できない
}

fn main() {
    failed_borrow();
}

// 以下のコンパイルエラー
error[E0597]: `_x` does not live long enough
  --> src/main.rs:9:22
   |
4  | fn failed_borrow<'a>() {
   |                  -- lifetime `'a` defined here
...
9  |     let y: &'a i32 = &_x;
   |            -------   ^^^ borrowed value does not live long enough
   |            |
   |            type annotation requires that `_x` is borrowed for `'a`
...
16 | }
   | - `_x` dropped here while still borrowed

 

[まとめ]

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

ライフタイムなんもわからん...。

 

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

github.com