こんにちは。Hackの深淵へようこそ。
HHVMの心臓部で型チェッカーと日々対峙していると、言語の「型」が単なる制約ではなく、バグという名のノイズを消し去るための「極めて精密なフィルター」であることに気づかされます。
今回は、Hackにおける関数型プログラミングの要、「高階関数とクロージャの型定義」について深掘りしましょう。ここを掌握すれば、あなたのコードは劇的に堅牢で、かつエレガントになります。
—
1. 関数を「型」として扱う:その本質
Hackにおいて、関数を引数や戻り値として扱う際、私たちは「関数型(Callable Types)」という武器を使います。
よくある初学者のつまずきポイントは、関数のシグネチャ(引数と戻り値の型)をどう表現するかです。Hackでは以下の形式が基本となります。
// (引数の型リスト): 戻り値の型
(function(int, string): bool)
この記法、一見すると直感的に見えるかもしれませんが、HHVMの型システムから見ると、これは単なるラベルではなく、「この関数はどんな入力を受け取り、どんな結果を返すか」という契約書そのものなのです。
2. 実践:クロージャを引数に渡す高階関数
例えば、リストをフィルタリングする処理を考えてみましょう。
<<__EntryPoint>>
function main(): void {
$numbers = vec[1, 2, 3, 4, 5];
// 「偶数かどうか」を判定するクロージャを渡す
$evens = filter_list($numbers, $n ==> $n % 2 === 0);
\var_dump($evens);
}
// 高階関数の定義
// 第2引数 $predicate は「intを受け取りboolを返す関数」と明示
function filter_list(vec
$result = vec[];
foreach ($items as $item) {
if ($predicate($item)) {
$result[] = $item;
}
}
return $result;
}
ここで注目すべきポイント
- 型推論の限界と明示: Hackのコンパイラは非常に優秀ですが、高階関数の引数に対しては、明示的に型を書くことが「読みやすさ」と「安全性」のバランスを最適化します。
- `$n ==> $n % 2 === 0`: このラムダ式(クロージャ)は、コンテキストから自動的に型が推論されますが、内部で行われていることは、上記の `(function(int): bool)` という契約への適合確認です。
3. 陥りやすい罠:なぜ「型エラー」が出るのか?
開発現場でよく見かけるエラーパターンを挙げておきます。
エラーパターン1:戻り値の不一致
// エラー: 戻り値が string になっているが、定義では bool が期待されている
$fn = (int $n): string ==> “is_” . (string)$n;
エラーパターン2:非nullableな関数型にnullを渡す
// 型定義は (function(): void) だが、null を代入しようとしている
function execute((function(): void) $callback): void { … }
execute(null); // Type Error!
もし「関数を渡さない場合もある」という設計なら、nullable型である `?(function(): void)` と定義するのがHack流の作法です。
4. チーフアーキテクトからのアドバイス:型エイリアスを活用せよ
複雑な高階関数を書くとき、シグネチャをそのまま書くとコードが汚染されます。そんな時は `type` キーワードで型に名前をつけましょう。
// 型に名前をつけることで、意図が明確になる
type Predicate = (function(int): bool);
function filter_list(vec
// …
}
こうすることで、コードの可読性が飛躍的に向上します。型に名前を付けることは、あなたのドメイン(業務知識)を型システムに直接マッピングする行為です。
—
まとめ:Hackの「型」は守護神である
関数型プログラミングをHackで導入するということは、単に便利な書き方を使うということではありません。「どのデータがどのように変換されるか」というデータの流れを、コンパイル時に確定させることです。
- 関数は `(function(ArgType): ReturnType)` で表現する。
- 複雑なシグネチャは `type` エイリアスで抽象化する。
- nullを許容するなら `?` を忘れない。
ここをクリアすれば、あなたはもうHackの基礎をマスターしたも同然です。次は、非同期処理(Async)と型システムの融合という、Hackの真骨頂に挑んでみてください。
何か分からないことがあれば、いつでもHHVMのソースコード……ではなく、私に聞いてくださいね。あなたの挑戦を応援しています。