関数型プログラミング近年、関数型プログラミングの重要性はいろんなところで叫ばれています。Javaの最新バージョンに関数型プログラミングに関する新機能が加わりました。Rubyも昨今、関数型プログラミングへのサポートが手厚くなってきています。プログラミングの教科書の大手、オライリー社から、Javascriptで関数型プログラミングを行うための解説書が発行されました。関数型プログラミングへの注目度は高まってきています。みなさんは既にオブジェクト指向が何か、を知っています。関数型プログラミングとは何か、胸を張って語れる人は、周りに見当たらないかと思います。関数型プログラミングとは何か、何が良いのか、ということについての、よいまとめは見つけることはできませんでした。この記事を読む方の中で、「関数型プログラミングを取り入れるか・取り入れないか」で切実に悩んでいる人は、おそらくいないでしょう。この記事はあまり細かいところに立ち入りません。関数型プログラミングを使う側の立場に立って、利点や向き・不向き、それが導くスタイルを書きました。みなさんは鳥のように飛んで、高い空から、関数型プログラミングとは何か、何が良いのか、を見渡してください。ふたつのアプローチの比較オブジェクト指向的アプローチは、名前をつけてプログラムを整理する。関数型プログラミング的アプローチは、汎用部品でなんとかする。オブジェクト指向的アプローチGoogleが近年リリースした言語、Goには、”継承”を直接サポートする仕組みが無いことが話題になりました。Foundationは、ライブラリ自体はC言語で書かれているにもかかわらず、その設計方針は明確にオブジェクト指向です。継承やクラスは、オブジェクト指向の必須条件ではありません。オブジェクト指向の本質とは、何でしょうか。その本質とは"名前をつけて対象を識別し、それを扱うこと"、にあります。プリミティブなオブジェクト指向の対象は、ファイルハンドラです。あるファイルを開いて、読み込んで、あるいは書き込んで、ファイルを閉じる。これらの処理をまとめたら、わかりやすいですよね?対象に関する処理を、対象の周りにまとめる。これがオブジェクト指向の基礎的な理念です。識別することとイコールで比較できることは、とても良く似ています。イコールによる比較は、オブジェクト指向では鬼門であることが知られています。java"をご参照ください)。名前をつけて識別する対象は、フワフワしていてはいけません。"軍人の階級"をオブジェクトにしたとしましょう。"大佐"クラスのある兵士は名前のフィールドや、性別のフィールドを持っているでしょう。ところで彼が昇格したときに何が起こるでしょうか。新たに"少将"クラスのインスタンスが作られます。"大佐"クラスを破棄する前に、名前、性別、その他沢山のデータを引き継がなくてはいけません。フィールドを増やしたい場合はその都度コードに修正を加える必要があります(*)。イコール比較を避けたい。対象は不安定なものではいけない。何に名前をつけて、識別するか。そこにオブジェクト指向技術者の熟練度が現れるのです。関数型プログラミング的アプローチ一方、関数型プログラミングでは、特定の何かに名前をつけるより、極力、汎用部品でなんとかしようとします。小さな関数を、集めて撚り合わせて、新しい関数を作る。関数自体をリストなどのデータ構造に詰めることもよく行われます。実は、関数型プログラミングというのは本質を表していません。その真の名は、"値指向プログラミング"です。関数をはじめとして、リスト・ツリーのようなコンテナ、手続きを抽象化したもの、回路を抽象化したもの。あらゆる対象を値として、合成し、ときに分解し、新しい値を作ります。変数という概念は必要ありません。変数に適用する処理を作りあげることが、とても簡単だからです。四則演算が定義されたデータを詰めたデータ構造もまた、四則演算可能だったり。値をイコール比較することも、なんのそのです。誤解を恐れずに言うと、オブジェクト指向がトップダウンなのに対し、関数型プログラミングはボトムアップです。読みやすい・理解しやすい関数型プログラミングをサポートする言語には、沢山の汎用部品が定義されています。"コンテナ"一般を表すもの。"手続き"一般を表すもの。"回路"一般を表すもの。木やリストのような、各所を周って要素に変更を加えられるデータ構造一般。再帰的に"畳み込めるデータ構造"一般を表すもの。理解するのはとても容易です。これが関数型プログラミングの大きな利点です。追記:また、汎用部品と型のお陰で、ライブラリのドキュメントが圧倒的にひきやすい、というメリットも有ります。Togetterまとめ書きやすい関数型プログラミングは「厳密な事前設計を必要とするため、簡単なことをやるのにも時間が掛かる」。誤解されていますが、これはウソです。スクラッチでプログラムするのは、非常に手軽です。[1,2,3][2,4,6]邪魔な”儀式”や、"おまじない"のコードが徹底的に撤廃されているためです。関数型プログラミングのコードは、潔癖かつ濃密です。y)が定義されているとき、hoge(3)はなんの意味も持ちませんが(コンパイルでコケますが)、関数型プログラミングでは意味があり、実際に有用です。上の例では、「掛け算をする」(*)関数は、二引数関数ですが、それに引数を渡して作られた「2を掛ける」関数(*2)は、一引数関数になります。関数型プログラミングでは、「簡単なことは簡単にでき、複雑なことは複雑にできる。間違ったことは殆どできないか、全くできない」。多くのバグは、コンパイルエラーとして検出されます。静的型付けの力によって、コード補完は非常に強力になっています。インテリセンスの比ではないです。HaskellWiki)。やってくる未来には、プログラムをテキストエディタで書くことは時代遅れになっているでしょう。統合環境のサポートで、バグやミスの少ない、スムーズなプログラミングができます。その環境で動くプログラミング言語は、関数型プログラミングをサポートした言語なのです。いつ関数型プログラミングか以下の様な兆候を感じたら、あなたはそのプログラムを関数型プログラミングで書くべきです。"人工物"クラスが増えてきた。Builderパターン、Strategyパターン、Commandパターン、Interpreterパターンが増えてきた。DI注入のとき、コンストラクタ注入にするか、セッター注入にするか、いつも迷う。一般に、オブジェクト同士の相互作用が複雑になるほど、オブジェクト指向では手に負えなくなっていきます。いうときは、オブジェクトを直接扱わず、替わりにその"相互作用"を扱うことで、複雑さを軽減するアプローチが有効です。それこそが関数型プログラミング的アプローチです。初心者にとっては読みやすい・理解しやすい特にオブジェクト指向が有効なのは、プログラミング初心者がそのコードをいじるかもしれないときです。関数型プログラミングは、強固さと柔軟さの代償として、高い学習コストを伴います。そのため、初学者にとってはハードルが高いのです。扱う対象があまり複雑でない時は、書きやすいオブジェクト間の相互作用が複雑でなく、着目している(名前をつけている)概念が安定しているとき。プログラムをいじる人たちの間で共通理解が図れているならば、オブジェクト指向が有利です。いう機能によって、レガシーな言語で扱えなかった、巨大な数を扱うことができます。分数を扱うことができます。関数型プログラミングで書かれたプログラムは、正確さが要求される、金融関連の業界で使われています。手続きとしてパーサーを記述できるので、テキスト処理プログラムはより理解しやすく、メンテナンスしやすいものになります。彼の書いた複雑な正規表現は、半年後には(書いた本人でさえ)理解できなくなっていることでしょう。手続き一般を扱うことができるので、途中で割り込みのある手続きの表現も容易です。関数型プログラミングをサポートしていない言語ではコルーチン(ファイバー)などをつかってなんとかするしかありません。なくば、非並行処理では普通に関数として記述できるところを、並行処理のために、Builder,Strategy,Command,Interpreterパターンを駆使して書き直すことになります。Javascript使いの方は、Deferredなどの構造を使うでしょう(http://qiita.com/KDKTN/items/4c6986049d204f0645d8)。C++使いの方はBoostで頑張りましょう。破滅的に解りにくいコンパイルエラーメッセージと格闘してください。レシピもう少し簡単な例をあげます。あなたは、あるレシピにしたがって、自動的に料理を行うマシンの制御プログラムを書いているとしましょう。料理のレシピは、"手続き"ですよね?たとえば、カレー。飴色になったら、肉を加えて炒める。