PHPの `callable` は「地雷」である。Hackで関数型アーキテクチャを再構築せよ。
Hackのチーフアーキテクトとして、一つだけ断言しておく。PHP的な `callable` を使い続けている限り、君のコードに安全な未来はない。
`callable` は単なる「型」ではなく、実行時までその正体が不明な「ブラックボックス」だ。文字列、配列、クロージャ…何が飛んでくるかわからないものに、どうやって信頼を置くというのか。Hackの静的解析器(HHVMの心臓部)は、そんなあやふやな存在を極限まで嫌う。
今回は、PHPのコールバック地獄をHackの堅牢な型システムで浄化し、HSL(Hack Standard Library)を駆使した「落ちないコード」の設計術を伝授する。
—
1. なぜ `callable` は現代の設計で許されないのか
PHPの `callable` は、型安全性において「無防備」そのものだ。
// 危険なPHP的設計の残滓
function execute(callable $callback): void {
$callback(); // ここで何が起きるか、静的解析では一切保証できない
}
このコードでは、引数の数も、戻り値の型も、内部で投げられる例外すらも予測不能だ。コンパイラは何も助けてくれない。これでは、リファクタリングのたびに本番障害の恐怖に怯えることになる。
2. 関数型シグネチャによる「契約」の締結
Hackでは、`callable` を「特定の型を持つ関数」として厳格に定義する。これが関数型インターフェースの第一歩だ。
改善された設計パターン
引数と戻り値を明示した「型エイリアス」を使うことで、コンパイル時に呼び出し元と呼び出し先の整合性を強制させる。
namespace App;
// 関数シグネチャを型として定義する
type Processor = (string, int) -> bool;
class TaskRunner {
public function run(string $data, int $priority, Processor $processor): void {
// コンパイラは、$processor が (string, int) -> bool であることを保証する
if ($processor($data, $priority)) {
// 成功時の処理
}
}
}
この設計なら、もし誰かが誤った引数で `$processor` を呼び出そうとすれば、HHVMがビルド時に容赦なくエラーを吐き出す。これがHackの強みだ。
—
3. HSLとクロージャによる非同期フローの制御
実務の現場で多いのは、非同期API連携における「コールバックのネスト」だ。ここでPHPのクロージャをそのまま使うと、メモリリークやコンテキストの汚染を招く。
HSLの `vec` や `dict`、そして `shape` を組み合わせ、データフローをパイプライン化せよ。
実務で使える:関数合成によるパイプライン設計
use namespace HH\Lib\{Vec, Str};
type Transformer = (string) -> string;
/
- 関数型アプローチによる変換パイプライン
/
function applyPipeline(vec
return Vec\map($inputs, $input ==> {
// 関数型的に変換を畳み込む
return Vec\reduce($transformers, ($acc, $f) ==> $f($acc), $input);
});
}
// 利用例
$transformers = vec[
(string $s) ==> Str\trim($s),
(string $s) ==> Str\uppercase($s),
];
$result = applyPipeline(vec[” hack “, ” language “], $transformers);
// vec[“HACK”, “LANGUAGE”]
このコードの美しさは、中間状態を保持する変数が存在しないことにある。`Vec\reduce` を用いることで、実行順序が確定し、副作用が排除されている。HHVMはこの構造を最適化し、ループ展開やインライン化を極限まで押し進める。
—
4. パフォーマンスの真実:なぜこれが速いのか
「関数を渡すのはオーバーヘッドではないか?」という議論がある。しかし、HHVMのJITコンパイラを侮ってはならない。
1. インライン化の機会: 型が確定しているため、JITは呼び出し先の関数を呼び出し元のコンテキストにインライン展開できる。`callable` のような「動的ディスパッチ」を排除することで、分岐予測のミスを劇的に減らす。
2. メモリの局所性: クロージャがキャプチャする変数をHHVMはスタックまたは最適化されたヒープ上に配置する。`use` 句による無駄なメモリコピーは、Hackの型システムによって最小限に抑えられる。
—
結論:コードは「文書」ではなく「契約」である
PHPの `callable` は、書いた本人だけが理解できる「メモ」に過ぎない。対して、Hackの型定義は、未来の自分やチーム全員に対する「契約」だ。
- `callable` を捨てろ: 代わりに `(T) -> R` のような具体的なシグネチャを型エイリアスとして定義せよ。
- HSLを活用せよ: `Vec`, `Dict`, `Str` 名前空間にある高階関数は、君が自前で書くループよりも遥かに安全で、最適化されている。
- 副作用を分離せよ: 関数型インターフェースの真の価値は、テストの容易性にある。入出力が型で保証されていれば、モックを作る必要すらなくなる。
君たちのプロダクションコードが、静的型チェックという最強の盾に守られ、HHVMという最速のエンジンの上で走ることを期待している。
さあ、古いPHPの残滓をリファクタリングして、Hack本来の力を解放しろ。