こんにちは!Hackの静的型システムとHHVMの裏側の世界へようこそ。チーフアーキテクトの私です。
他のプログラミング言語からHackの世界に飛び込んできた開発者の多くが、最初に「おや?」とつまずくポイント、そして同時にHackの美しさに魅了される瞬間があります。それが「データの複数戻り値の扱い方」です。
今回は、配列(Array)のインデックスアクセスという泥臭い世界から脱却し、Hackの強力な `Tuple`(タプル)型と直感的な分解構文を使って、型安全で美しいコードを書く極意を一緒にマスターしていきましょう。ここをクリアすれば、Hackの型システムの恩恵を肌で感じられるようになりますよ!
—
1. なぜ「配列ベースの複数戻り値」は危険なのか?
PHPや、動的型付けの香りを残したコードを書いていると、関数から複数の値を返したいときに、つい次のような配列(Array)を使ってしまいがちですよね。
<<__Strict>>
namespace HackMasterclass;
// ユーザー情報をデータベースから取得して、[名前, メール, 年齢] の配列を返す関数(アンチパターン)
function fetch_user_legacy(int $id): array
// 実際にはDBから取得する処理
return [“Alice”, “alice@example.com”, 30];
}
このコード、一見すると問題なさそうに見えますが、呼び出し側で大変なことになります。
<<__Strict>>
// 呼び出し側
<<__EntryPoint>>
function main_legacy(): void {
$data = fetch_user_legacy(1);
// インデックス「1」が何を表しているか、記憶に頼るしかない…!
// もしインデックスの順番が変わったら? 型は `mixed` なのでコンパイラは何も守ってくれません。
echo “名前: ” . $data[0] . “\n”;
echo “メール: ” . $data[1] . “\n”;
}
🧠 アーキテクトからの警鐘:
`array
—
2. 救世主:`Tuple` 型による型安全な複数戻り値
そこで登場するのが `Tuple`(タプル)型 です。
タプルとは、「固定長かつ、各要素の型が厳密に決まっている直積型」のことです。Hackでは、括弧 `(T1, T2, …)` を使って表現します。
先ほどのユーザー取得関数を、Tuple型を使って書き直してみましょう。
<<__Strict>>
namespace HackMasterclass;
// [名前(string), メール(string), 年齢(int)] を確実に返す
function fetch_user(int $id): (string, string, int) {
// 各要素の型がシグネチャと完全一致している必要がある
returntuple(“Alice”, “alice@example.com”, 30);
}
> 💡 ワンポイントメモ:
> Hackではタプルの構築に `tuple(“a”, “b”, 1)` もしくは単に `(“a”, “b”, 1)` のリテラル構文が使えます。型定義側は必ず `(string, string, int)` のように括弧で囲みます。
これで、関数が「何を・どの順序で返すか」が型レベルで完全に担保されました。
—
3. リスト代入(Destructuring)による優雅な分解
型が安全になっただけでなく、Hackにはタプルの値を一瞬で変数にバラす(分解する)ための非常にスマートな構文が用意されています。それがリスト代入(Destructuring)です。
実際のコードで見てみましょう。
<<__Strict>>
namespace HackMasterclass;
<<__EntryPoint>>
function main(): void {
$userId = 1;
// タプルをそのまま個別の変数に美しく分解!
list($name, $email, $age) = fetch_user($userId);
// IDEの補完も、型チェッカーの解析も完璧に効く
echo “名前: {$name} (年齢: {$age}歳)\n”;
echo “連絡先: {$email}\n”;
}
この分解構文の素晴らしいところは、左辺の変数 `$name`, `$email`, `$age` の型が、右辺のタプルの型定義(`string, string, int`)から自動的に推論される点です。手動で型を書く必要すらありません。
—
4. 陥りやすい文法エラーと型チェッカーの挙動
ここで、Hackの厳格な型チェッカー(hhvm)がどのようにあなたを守ってくれるか、いくつかの「やりがちなミス」を見ておきましょう。
エラーケース 1: 要素数のミスマッチ
// 戻り値は3つの要素を持つタプルなのに…
list($name, $email) = fetch_user(1);
// ❌ コンパイルエラー!
// タプルの要素数(3つ)と代入先(2つ)が一致しません。
配列であれば実行時まで気づかないバグが、Hackならビルド(型チェック)の瞬間に検知されます。
エラーケース 2: 型の不一致による代入
// $age は int のはずなのに、stringを受け取ろうとしたら?
list($name, $email, $age) = fetch_user(1);
// もし関数側で $age の位置に文字列を返していたら、
// $age を数値として扱おうとした瞬間に型チェッカーが怒ってくれます。
—
5. まとめ:配列脳からTuple脳へ切り替えよう
今回は、配列ベースの曖昧な戻り値から脱却し、`Tuple` 型とリスト代入を使って型安全なコードを書く手法を解説しました。
- 配列のインデックスアクセスは、型が失われ(`mixed`になり)、バグの温床になります。
- `Tuple` 型 `(T1, T2, …)` を使えば、固定長の複数戻り値を明確に型定義できます。
- `list(…)` 構文 を使えば、可読性を落とさずにエレガントに変数を分解できます。
「複数の値を返したいときは、まずTupleが使えないかを考える」。
この習慣を身につけるだけで、あなたの書くHackコードの堅牢性は劇的に跳ね上がります。
ここをクリアしたあなたなら、もうHackの静型システムの心地よさを十分に実感できているはずです。
さあ、次のコードブロックへ進みましょう。あなたのハッキングを応援しています!