Edited at

オブジェクト指向vs関数型プログラミングの壮絶な宗教戦争っていつしてたの……?

More than 3 years have passed since last update.

なんか荒れてますが、私も一言いいたいです!!

オブジェクト指向がそうであるように、関数型も銀の弾丸ではありません!!!

-


参照透過性はすばらしい

この記事をぼやーんと眺めてました。

高精度煽り除去フィルタを通して読むと、関数型のアプローチがよい、と言う話ですね。

実際コードを書いてると、自分の書いたコードに関するバグは、体感、8割くらいが副作用に起因するものです。

副作用があると、呼び出し元が考慮すべきパターンが増えます。Mの状態を持つオブジェクトと、Nの状態を持つオブジェクトをつなぐと、MxNのパターンになるわけです。これはつなぐたびに積算されるため、爆発します。

副作用が無い場合、状態数は1なわけです。1x1は?1です!!よって、状態の組み合わせ爆発は起きません。考慮すべきは、入力値のパターンだけで十分なわけです。

他にもいろいろメリットが!!

すばらしき参照透過性!!関数世界最高ですね!!!


でも話はここで終わらない

ですが、実際の開発では、ここで話は終わりません。


作用だけではプログラムは組めません!!

論理だけでは現実世界に作用を及ぼせません。

画面の表示、ディスクの書き込み、サウンドのプレイバック、etc...、プログラムが意味を持つためには、 必ず副作用が必要になります

関数型世界では、副作用は外に追い出すことで、すばらしき関数型世界を守ります。

要するに、この二次元配列とx,yの構造体を返したら、x,yの位置に二次元配列で表現された画像を表示する事を、 関数世界外 が行ってくれるのです。

よさそうです。ですが、これは暗黙の前提を一つ置いています。 必要な副作用がすべて提供されている という・・・。

これは無茶な前提です。たとえばLeap Motionを使ったCooooolなゲームを作りたい、という場合、関数型世界で提供されてないと手も足も出ません。

おっとOpenGLもOpenALも、GLFWも無いかもしれません!!このようなライブラリをどうにかして呼ぶ必要があるわけです。そこで、ffiなりなんなり、関数型世界外の力を借りる必要があります。

そうです、 無いなら作らないといけないのです。 だってエンジニアだもん!!

ですが、関数型世界で提供されていない副作用を扱うためには、いらぬ苦労を強いられるのです。


作用だけでは時間変化を扱えません!!

前FRPっていってたじゃないって?

そうですが、これも上とかぶるのです。

FRPなんですが、関数のトリガは関数世界外から行う必要があるわけです。 関数世界からは起動できません。

すべての可能なトリガが提供されていたらいいですが……

そうです、 無いなら作らないといけないのです。 だってエンジニアだもん!!

ですが、関数型世界で提供されていない副作用を扱うためには、いらぬ苦労を強いられるのです。

(再び!)


関数型世界が世界を取るためには?

関数型世界では、副作用は特別なものです。これを関数世界の「外側」とします。

その外側をエンジニアが記述する必要がなくなった時、関数型世界の理想郷はひらかれるのではないでしょうか。


余談


関数型言語で組めばすぐ並列化できるという幻想

なんでこれがまかり通ってるのか疑問です。

関数型言語でも、並列化を行うためには思考コストを払う必要があります。

これに関しては単純な例を挙げれば十分かと思います。


  • fの計算結果にgが依存していると、fが終了しないとgを計算できない(暗黙のうちに正格評価を前提にしてたため、書き直しました)

計算結果に依存しないように、注意深くアルゴリズムを選択する必要があるのです。

その思考コストが相対的に安くなるのは間違いないですが、無視できるほど少なくはなりません。

こと並列化に関しては、関数型言語よりも、ストリーム指向の言語の登場が待たれます。


ぼくのかんがえたさいきょうのぱらだいむ

オブジェクトは問題を分割し、副作用を扱うのが得意です。

関数は論理記述に優れています。

手続きは、時間変化を伴う処理を記述できます。

関数で書いたオブジェクトを、手続きで指示を与える。これが理想ではないでしょうか。

プログラミング言語も、実際そのように動いてるように見えます。


  • Java 手続き、オブジェクト世界に関数型を導入(lambda)

  • JavaScript 関数型、オブジェクト世界に手続きを導入(yield)


結局React.jsって?

React.js触りました!!!

React.js、というよりVirtual DOMのすごさは、関数型vsオブジェクト指向の文脈でとらえるとわかり辛いです。

なので、誰もが納得する、以下の事実を利用します。


  • 差分更新は実行速度は速いけどエンバグしやすい

  • 全更新はバグりにくいけど実行速度が遅い

な ら ば !!


  • React.jsがVirtual DOM -> DOMの差分更新を受け持ってあげるから、君たちは安心してVirtual DOMを全更新してね!!

です!