Rust dojo第14回を開催した

第14回です。

前回はこちら。

kdnakt.hatenablog.com

 

 

[第14回の様子]

2021/10/13に第14回を開催した。

 

内容としてはRust By Example 日本語版の「4.1. ミュータビリティ」、「4.2. スコープとシャドーイング」、「4.3. 宣言」に取り組んだ。

 

おやすみの人が多かったからか参加者は少なめで、全部で6人くらい。

 

Slackでの書き込みも相変わらず少なめ。

f:id:kidani_a:20211015152023p:plain

f:id:kidani_a:20211015152112p:plain

 

来週はお待ちしてます!

f:id:kidani_a:20211015151941p:plain

 

[学んだこと]

fn main() { 
  let _immutable_binding = 1;
  _immutable_binding += 1;
}
// 以下のコンパイルエラー
2  |     let _immutable_binding = 1;
   |         ------------------
   |         |
   |         first assignment to `_immutable_binding`
   |         help: consider making this binding mutable: `mut _immutable_binding`
...
3  |     _immutable_binding += 1;
   |     ^^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable
  • mut構文を利用すると変更できる
fn main() { 
    let mut mutable_binding = 1;
    println!("Before mutation: {}", mutable_binding);
    // Before mutation: 1
    mutable_binding += 1;
    println!("After mutation: {}", mutable_binding);
    // After mutation: 2
}
fn main() {
    // 新しいスコープ
    {
        let short_lived_binding = 2;
        println!("inner short: {}", short_lived_binding);
    }
    println!("outer short: {}", short_lived_binding);
}

// 以下のコンパイルエラー
error[E0425]: cannot find value `short_lived_binding` in this scope
 --> src/main.rs:21:33
   |
21 | println!("outer short: {}", short_lived_binding);
   | ^^^^^^^ not found in this scopeす
fn main() {
    let long_lived_binding = 1;
    println!("outer long: {}, {:p}", long_lived_binding, &long_lived_binding);
    // outer long: 1, 0x7ffde1f6177c

    { // 別スコープ
        let long_lived_binding = 5_f32;
        println!("inner long: {}, {:p}", long_lived_binding, &long_lived_binding);
        // inner long: 5, 0x7ffde1f6183c
    }
    // 元のスコープ
    println!("outer long: {}, {:p}", long_lived_binding, &long_lived_binding);
    // outer long: 1, 0x7ffde1f6177c
    
    // シャドーイングによりポインタが変わっている
    let long_lived_binding = 'a';
    println!("outer long: {}, {:p}", long_lived_binding, &long_lived_binding);
    // outer long: a, 0x7ffde1f61914
}
  • 4.3. 宣言
  • 変数宣言と初期化は別タイミングでもよい
fn main() {
    // 宣言
    let a_binding;
    {
        let x = 2;
        // 初期化
        a_binding = x * x;
    }
    println!("a binding: {}", a_binding);
    // a binding: 4
}
  • あ初期化していない変数を利用しようとするとコンパイルエラー
fn main() {
    let another_binding;
    println!("another binding: {}", another_binding);
}

// 以下のコンパイルエラー
error[E0381]: borrow of possibly-uninitialized variable: `another_binding`
  --> src/main.rs:20:37
   |
20 |     println!("another binding: {}", another_binding);
   |                                     ^^^^^^^^^^^^^^^ use of possibly-uninitialized `another_binding`
  • Dropというトレイトがある:いわゆるデストラクタ的なやつ、オブジェクトが破棄されるときに呼ばれる
fn main() {
    let _a = A; // main関数終了後にスコープを外れる
    println!("End of main()");
    // End of main()
    // Drop A
}

struct A;

impl Drop for A {
    fn drop(&mut self) {
        println!("Drop A");
    }
}
  • ただ変数を宣言しただけで初期化しないとdrop()は呼ばれない
fn main() {
    let _a: A;
    // なにも出力されない
}

struct A;

impl Drop for A {
    fn drop(&mut self) {
        println!("Drop A");
    }
}
  • 上記以外にも、シャドーイングしたら前のオブジェクトがドロップされる実験とか、いろいろやった。

 

[まとめ]

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

Rustのスコープ、ちょっとだけ理解できた気がする。

 

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

github.com