📦

コレクション — ArrayとHashがVecとHashMapになると

型が固定された世界の配列とハッシュマップ

Vec — RubyのArray

# Ruby — どんな型でも混ぜられる
arr = [1, "hello", true, nil]

// Rust — 1つの型のみ
let arr: Vec<i32> = vec![1, 2, 3];
// vec![1, "hello"]  // コンパイルエラー

基本操作:

let mut v = vec![1, 2, 3];
v.push(4);              // Ruby: arr.push(4) / arr << 4
v.pop();                // Ruby: arr.pop
v.len();                // Ruby: arr.length
v[0];                   // Ruby: arr[0]
v.contains(&3);         // Ruby: arr.include?(3)
v.is_empty();           // Ruby: arr.empty?

HashMap — RubyのHash

# Ruby
h = { name: "sehwa", age: 30 }
h[:name]  # "sehwa"

// Rust
use std::collections::HashMap;

let mut h = HashMap::new();
h.insert("name", "sehwa");
h.insert("age", "30");  // 値も同じ型でなければならない

h.get("name");  // Option<&&str> — なければNone(nilではない!)

Rubyでh[:missing]はnilを返す。Rustでh.get("missing")Noneを返す。Option処理が必要。

entry API — RubyのHash.new(default)に対応

# Ruby
counts = Hash.new(0)
words.each { |w| counts[w] += 1 }

// Rust
let mut counts = HashMap::new();
for word in &words {
    *counts.entry(word).or_insert(0) += 1;
}

entry().or_insert(0)は「キーがなければ0を挿入し、いずれにせよ値の可変参照を返す」。

HashSet — RubyのSet

use std::collections::HashSet;
let s: HashSet<i32> = [1, 2, 3].iter().cloned().collect();
s.contains(&2);  // true

ソート

let mut v = vec![3, 1, 2];
v.sort();                          // [1, 2, 3] — 元を変更
users.sort_by(|a, b| a.age.cmp(&b.age));

Rustのsort()元を変更する(mut必要)。元を保持するなら.clone()してからソート。

型が1つという制約

Rubyの[1, "hello", true]は使えない。複数の型を入れたければenumを使う。

enum Value {
    Int(i32),
    Str(String),
    Bool(bool),
}
let mixed: Vec<Value> = vec![
    Value::Int(1),
    Value::Str("hello".into()),
    Value::Bool(true),
];

面倒だが、取り出す時に型チェックが強制されるのでランタイムエラーが減る。

キーポイント

1

Array → Vec<T>、Hash → HashMap<K, V> — 型パラメータ必須

2

Hash.get()はOption返却 — nilの代わりにNone

3

entry().or_insert()でデフォルト値パターンを実装

4

複数の型を入れるにはenumでラップ

メリット

  • 型が固定されているので取り出す時に型変換が不要
  • get()がOption返却なのでインデックスエラーがない

デメリット

  • Rubyの柔軟な配列操作に比べて型制約が不便
  • HashMapの初期化がRubyのHashリテラルより冗長

ユースケース

データグルーピング/カウント — HashMap + entryパターン APIレスポンスパース — Vec<Item>で型安全に