Rust dojo第8回を開催した

第8回です。

前回はこちら。

kdnakt.hatenablog.com

 

 

[第8回の様子]

2021/09/01に第8回を開催した。

今回は最初から無事参加できた。

 

内容としてはRust By Example 日本語版の「2.3. 配列とスライス」を読んで手を動かした。

 

参加者は全部で9人。ちょっと減ったけど、相変わらずなかなか盛況である。

今回も、前回終了時に決めておいたメンバーがドライバーを担当。

 

今週も開催前後のSlackでのやりとりがたくさん🎉

 

遅れても参加してえらい!

f:id:kidani_a:20210902001007p:plain

 

楽しく配列のお勉強。

f:id:kidani_a:20210902001232p:plain

f:id:kidani_a:20210902000830p:plain

f:id:kidani_a:20210902000354p:plain

 

また参加者が増えるかも!

f:id:kidani_a:20210902000452p:plain

 

[学んだこと]

  • 2.3. 配列とスライス
  • 配列は単一の型のオブジェクトの集合
  • メモリ上の連続した領域に保存される
  • サイズはコンパイル時に決定されて、[T; size]型でサイズを指定できる
  • スライスは配列と似ているが、コンパイル時にはサイズが決定されていない
  • しかし後からサイズを変更できるわけではない:その場合は動的に拡張できるVectorを使う
  • スライスは配列の一部を借用するときに&[T]という型シグネチャで利用する
  • 配列を宣言するときはこんなかんじ
let xs: [i32; 5] = [1, 2, 3, 4, 5];

// 型宣言はなしでもよい
let xs = [1, 2, 3, 4, 5];
  • 配列を同じ値で初期化することもできる
let ys: [i32; 500] = [0; 500];

// 型宣言はなしでもよい
let ys = [0; 500];
  • 配列のインデックスは0からはじまる。
let xs = [1, 2, 3, 4, 5];
println!("first element of the array: {}", xs[0]); // 1
println!("second element of the array: {}", xs[1]); // 2
  • 配列のサイズを取得するときはlen()を使う
let xs = [1, 2, 3, 4, 5];
println!("array size: {}", xs.len()); // 5
use std::mem;
let xs = [1, 2, 3, 4, 5];
println!("array occupies {} bytes", mem::size_of_val(&xs));
// 20 bytes
// デフォルトはi32で32ビット=4バイト、4x5で20バイト
  • 配列を関数に渡すときに、自動的にスライスとして借用される
// この関数はスライスを借用する
fn analyze_slice(slice: &[i32]) {
    println!("first element of the slice: {}", slice[0]);
    println!("the slice has {} elements", slice.len());
}

let xs = [1, 2, 3, 4, 5];
analyze_slice(&xs);
// first element of the slice: 1
// the slice has 5 elements
  • 配列の一部を借用することもできる
fn analyze_slice(slice: &[i32]) {
    println!("first element of the slice: {}", slice[0]);
    println!("the slice has {} elements", slice.len());
}

let ys: [i32; 500] = [0; 500];
analyze_slice(&ys[1 .. 4]); // インデックス1から3までの要素をスライスとして借用
// first element of the slice: 0
// the slice has 3 elements
  • インデックスが範囲を超えている場合はコンパイルは通るが、実行時にパニックする
let xs = [1, 2, 3, 4, 5];
println!("{}", xs[5]);

// 実行時に以下のエラー
error: this operation will panic at runtime
  --> src/main.rs:46:20
   |
46 |     println!("{}", xs[5]);
   |                    ^^^^^ index out of bounds: the length is 5 but the index is 5
   |
   = note: `#[deny(unconditional_panic)]` on by default
  • 配列の中身を書き換える場合は、mutをつけてlet mut xs = [1, 2]のように宣言必要がある
let xs: [i32; 5] = [1, 2, 3, 4, 5];
xs[0] = 11;

// これはコンパイル時に以下のエラー
error[E0594]: cannot assign to `xs[_]`, as `xs` is not declared as mutable
  --> src/main.rs:14:5
   |
13 |     let xs: [i32; 5] = [1, 2, 3, 4, 5];
   |         -- help: consider changing this to be mutable: `mut xs`
14 |     xs[0] = 11;
   |     ^^^^^^^^^^ cannot assign
  • スライスを可変にするには少々手間がかかる:以下の2つが必要
    • 関数の引数として宣言している箇所でmutをつける
    • 配列をmutで宣言し、関数を呼び出す際にもmutをつける
fn analyze_slice(slice: &mut[i32]) {
    slice[0] = 23;
    println!("first element of the slice: {}", slice[0]);
    println!("the slice has {} elements", slice.len());
}

let mut xs = [1, 2, 3, 4, 5];
analyze_slice(&mut xs);
// first element of the slice: 23
// the slice has 5 elements
  • スライスを生成する際のインデックス指定も、配列のサイズを超えていると実行時にパニックとなる
    • ただし配列へのインデックスアクセスとはエラーメッセージがちょっと異なる
fn analyze_slice(slice: &[i32]) {
    println!("first element of the slice: {}", slice[0]);
    println!("the slice has {} elements", slice.len());
}

analyze_slice(&ys[1 .. 10]);
// thread 'main' panicked at 'range end index 10 out of range for slice of length 5', src/main.rs:42:20
// note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

 

[まとめ]

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

配列とスライスで遊んだ。エラーがいろいろ出て楽しい。

 

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

github.com