概要
FizzBuzz の問題を、 ラムダ計算 や コンビネータ のみで解く奇抜な面接回答例。 JavaScript を使いながら、 S や K などの基本コンビネータから構築。 Church数 や リスト、 再帰 もすべて関数のみで表現。 面接官との 会話形式 で進行し、途中で Yコンビネータ や 遅延評価 の話題も登場。 最後は FizzBuzz の完全なラムダ式まで展開し、徹底的な抽象化を見せつける内容。
FizzBuzzをラムダ計算とコンビネータで解く
- 面接官 Dana との会話形式で進行
- FizzBuzz の説明を求められ、 JavaScript で記述開始
- S、 K などの基本コンビネータを定義
- 例:
let S = (x) => (y) => (z) => x(z)(y(z));
- 例:
- I (恒等関数)、 B (合成)、 C (引数交換)、 W (自己適用)なども定義
- TRUE / FALSE などのブール値を関数で表現
- NOT、 IS_ZERO などの論理演算も関数のみで表現
- Church数 の定義と、 SUCC (後者)、 PRED (前者)、 ADD (加算)などを実装
- 再帰 実現のため、 Yコンビネータ を導入
- JavaScriptの 正格評価 ではスタックオーバーフローになるため、 Skoobert という遅延評価環境に切り替え
- extractNumber 関数でChurch数から通常の数値へ変換
- SUBTRACT (減算)、 MULTIPLY (乗算)、 MOD (剰余)などの算術関数もすべて関数合成で記述
- リスト構造 (CONS、FIRST、REST、EMPTY)や MAP、 FOLD、 RANGE なども関数で表現
- Fizz や Buzz の文字列も、アルファベットを数値で表現し、リストとして構成
- extractString でリストから文字列へ変換
- 数値を各桁のリストに分解し、文字列化する関数も自作
- 最後に FizzBuzz 判定ロジックを関数合成で実装
- 3の倍数でFizz、5の倍数でBuzz、15の倍数でFizzBuzz、その他は数値を文字列化
- 変数を一切使わず、すべて ラムダ式 の入れ子でFizzBuzzを実現
面接官とのやりとり・抽象化の極限
- Dana は途中で「for文が見当たらない」と困惑
- Church数 や Barendregt など、関数型プログラミングの用語が飛び交う
- Yコンビネータ の使用に「JavaScriptなら普通に再帰できる」と指摘される
- 文字列処理、数値変換もすべて関数で記述し、「抽象化の暴走」を体現
- 最後はFizzBuzzのロジックを S や K のみの入れ子で完全展開
- 面接官も「満足?」と問いかけるが、さらに変数を排除する徹底ぶり
まとめ・学び
- FizzBuzz という単純な問題でも、 ラムダ計算 や コンビネータ のみで解くと極端に抽象的・複雑になる
- 再帰 や リスト処理、 数値変換 もすべて関数だけで表現できることの証明
- JavaScript の評価戦略の違い(正格/遅延)にも注意が必要
- 「抽象化」「関数合成」「再帰」の極限を体験できる例
- 実用性よりも 理論的な面白さ や 関数型プログラミングの奥深さ を味わえる内容