関数型つまみ食い: 関数型とはプログラミング言語ではなく、プログラムデザインの問題であることに気づく

関数型プログラミングに精通していないプログラマにとって、「関数型」という言葉でまず思い浮かべるのは、Haskell や Erlang,Scala のような関数型言語や、Immutableなデータ構造、高階関数、ラムダ式、モナドと言った関数型プログラミングの道具立てだったりすることが多いのではないだろうか?

前回登場したゲームプログラマの James Hague 氏も、筆者と同じく、キャリア半ばで関数型の世界に足を踏み入れた越境者の一人だったが、その彼が、関数型言語 Erlang でのゲーム開発を経験して気がついたことがあると言う。それは、アプリケーション開発に純粋な関数(副作用のない関数)というコンセプトを導入することは、いわゆる関数型言語や関数型プログラミングとは全く関係ないということであった。

関数型というコンセプトの要は、ビジネスロジックを「データの変換」と捉えることにある。

functional1

関数というのは要するに「変換のルール」のことであるが、この関数が文字通り変換のルールのみを定義し(副作用がなく)、そして変換対象のデータを直接編集せずに、常に変換後のデータに丸ごと置き換えて行けば、システムの状態変化は常にアトミックに行われることになる。

functional2

このような形で、システムの状態遷移をシンプルにすることによって得られるメリットの大きさに、筆者の場合、関数型言語というよりもむしろ、Redux というフロントエンドのフレームワークを学ぶ中で気づかされた。

Redux はフロントエンドの状態管理を行うためのフレームワークである。オブジェクト指向に慣れているとアプリケーションの状態は個々のオブジェクトに分散するのが当たり前であるため、何故状態だけを独立して管理する必要があるのか、今ひとつピンと来ないこともあるかもしれない。GUIとオブジェクト指向というのは歴史的にも結びつきが強いため、この領域に関数型を適用するというのはどういうことなのか、これは筆者にとっても長年の疑問であった。

Redux は React というフレームワークとペアになっている。React はユーザーインタフェースをレンダリングするためのテンプレートエンジンで、入力データをテンプレートに当てはめて結果を出力するという、まさに関数としてデザインされている。そのため、テンプレート内で状態管理をすることは推奨されていない。状態は外部で管理して React 側に提供する必要がある。その状態管理を担うのが Redux である。

redux

Redux の仕組みは、上に書いたような関数型の状態管理そのままである。筆者にとって重要だったのは、これが JavaScript という、比較的慣れ親しんだ言語の上に構築されたフレームワークであったことだ。これによって「ああ、つまり関数型というのはフレームワーク(デザイン)なのだ」という気づきを得ることが出来た。

関数型デザインによって実現するシンプルな状態遷移のメリットは、Redux のプラグイン redux-logger によって出力されるログを見ると分かりやすい。

redux-logger

上のように、Redux で状態を管理していれば、そこで発生する全ての状態遷移は、

  1. prev state
  2. action
  3. next state

の繰り返しによってアトミックに行われる。何か問題が発生した時は、開発者自身があちこちにログを仕込んだりデバッガを活用せずとも、この状態遷移の内容を見れば何が起きたのか一目瞭然である。

Redux のドキュメントでは、関数型(functional)という言葉を出来るだけ使わずに説明を試みているようである。しかしながら、Prior Art にあるように、Redux の直系の先祖はブラウザで動く(ほぼ)純粋な関数型の環境 Elm であり、Elm は Haskell をベースにデザインされていることから、Redux は純粋関数型の思想を純粋関数型でない言語の上に実現したフレームワークだと言って差し支えないだろう。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中