初めての投稿です。
思っていることを書いてみましたが、文章があまり得意でないので、ご容赦ください。
最近、関数型言語が流行り始めています。
人によっては「大きなパラダイムシフトだ」と言います。
はたして、そうでしょうか。
自分の結論では、パラダイムシフトなどではなく、これまで足りていなかった事に気が付き始めただけ、だと思っています。
(誤解の無い様に補足しますが、関数型言語は非常に古くからあります)
かつては、オブジェクト指向もその様に言われていた時代があります。
しかし、今ではオブジェクト指向が当たり前となり、パラダイムシフト等とは言われなくなりました。
ただ、自分の考えでは、現在使われているオブジェクト指向は、「モドキ」とも「本質的でない」と思っています。
さらに、構造化指向も同様です。
ただ、自分は時代を経るに従って「よりリアルに近づいている」のだと思います。
リアルとは何か、もちろん現実です。
厳密に言えば、現実の人が協調しあって、実現されているシステム(この場合、コンピュータのシステムの事を示していない)の事です。
人が、何かをするにあたって、必ず仕組みや手順、手続きが存在します。更にその何かをするための役割を持った関係者が存在します。
これらをまとめて、自分は「システム」と呼んでいます。
前もって言いますが、自分は関数型言語を否定するわけでも、嫌っているわけでもありません。
むしろ、大歓迎です。
IT業界に就職し、システム開発に25年も携わっていますが、その長年の謎(の一部分ではありますが・・・)を解き明かしてくれると、期待しています。
ただ、オブジェクト指向も、(振り返って考えてみれば)構造化指向も、世の中の勘違いにより、正しい使われ方がされず、今もってデスマーチが繰り広げられているプロジェクトは、多々あると思います。
自分としては、全ての謎が解ければ、デスマーチなプロジェクトは撲滅され、高品質な(予測し得ない例外事項は除いて)システムができると確信しています。
なお、解くべき謎は、まだまだ沢山有ります。
さて、本題に戻ります。
まずは、それぞれの解釈を書きます。
(あくまでも、自分の解釈ですが、受け入れられないと思った人は、すぐに読むのを止めて、忘れてください。)
構造化指向です。
厳密には、「構造化指向設計方法論」だと思っています。
システム(この場合は、コンピュータ上で動作するシステムだと考えてください)を、処理を構造的に考え、設計する方法論です。
ただし、データが主体で、入力データに対し、処理によって、出力データがあると考えられます。
また、処理には、初期化/主処理/終了処理が存在します。
処理の中身は、代入/演算/ジャンプ(関数呼び出し)/ループ/条件分岐があり、その組み合わせで成り立っています。
更に、処理は、制御層と加工層(自分は、そう呼んでいます)の交互に積層化されるものと考えています。
非常に低水準なレベルで、設計していくための方法論です。
当時は、確立した設計方法論がなかったために、非常にもてはやされました。
代表的なプログラム言語は、C言語です。
次にオブジェクト指向です。
正確には、「オブジェクト指向分析設計方法論」です。
おや、「分析」という言葉が含まれています。
これが、オブジェクト指向の本質です。
構造化思考では、設計で出てくる要素は、演算やら条件分岐やらの非常に細かい単位のものです。
それに対し、オブジェクト指向では、クラスとクラス間の関連性を最小要素としています。
ここまで書いて、「違う!」と思った人はいると思います。
そう思った人は、例えば「ユースケース」や「コラボレーション」などがあると考えているかもしれません。
また、「状態どうなった?」と思っているかもしれません。
確かにそういったものも、オブジェクト指向の重要な要素ですが、実はこれらは、クラス分析、クラス間関連分析の、手法です。
つまり、オブジェクト指向においては、本質ではありません。
目的と手段は履き違えてはいけないということです。
とは言え、これらの手法を使いこなせば、そうでない場合に比べて、より精度の高いクラス分析、クラス間関連分析が出来ると思います。
逆に、これらの手法も知らないで、えいや!でやるので、失敗するわけです。
代表的な言語は、C++やJavaですが、自分は、C言語やVBでも十分に実現できると思っています。
意外、と言うか、そんなことはあり得ないと思う人もたくさんいると思いますが、オブジェクト指向の本質を知っているなら、理解できると思います。
最後に関数型言語です。
何故、これだけ「指向」ではなく「言語」なのでしょうか。
この答えは見つかっていませんが、とりあえず、以降も「関数型言語」と呼びます。
関数型言語の特徴として、「状態を持たない(ステートレス)」「関数に副作用を持たせない」等があります。
まずは、状態を持たない件ですが、これは大きな間違いだと筆者は考えています。
何故なら、
・状態を持たなければ、次に何をするかの判断が出来ない。
・関数そのものが、状態を表している。
からです。
(もちろん状態を持たない関数も作れます)
例えば、「迷路」を実施するプログラムを関数型言語で考えたとします。
「迷路」のルールは、割愛しますが、どなたでも知っていると思います。
スタートからゴールまで一本道なら迷路とは言わないので、分岐が必ずあります。
また、全ての分岐がゴールに着いたら、これも迷路とは言わないので、行き止まりがあったりします。
ある位置で分岐に差し掛かったとします。
当然、AないしはB、あればCの道に進むわけですが、A/B/Cのいずれを探索しているのか、記録しておかなければいけません。
関数の引数にする場合もありますが、A経路探索関数/B経路探索関数/・・・でも良いです。
そして、行き止まりであれば、分岐点に戻り、別の経路を探索します。
ここで、「ある経路は行き止まりだった、と言うことを、何処かに覚えていなければなりません。
つまり、言語としての表現方法はともかくとして、状態(もしくは記憶・記録)が必要になります。
従って、言語として「状態を持たない(ステートレス)」と言うのは、現実的にあり得ないのです。
また、最近の言語には「クロージャ」というものがあり、関数型言語から発生したものだと言われています。
これについても、クロージャが実行される瞬間に、その時の見える範囲のスコープの状況をスナップショットとして記録(=コンテキスト)し、クロージャ内から参照できるようになっています。
まさに、このスナップショットこそが「状態」となり、クロージャがその状態を保持していることになります。
むしろ、関数型言語はこの特性のお陰で、オブジェクト指向のクラスのように明示的な属性を定義しなくても、処理ができるわけです。
蛇足ですが、人の「脳」は関数型言語のこの特性に非常に近いのだと、筆者は思っています。
「脳(=脳細胞の集合体)」は、脳細胞と脳細胞が連結し、シナプスを通して信号をやり取りして、脳として活動しています。
関数型言語で言うと、脳細胞=関数、シナプスによる信号の伝達=関数の引数や戻り値、と考えられます。
そのため、関数型言語は人工知能を作るために最適なのだと思います。
だとすると、人としての記憶は何になるのか、それが先ほど示したコンテキストの集合だと思います。
ただ、プログラムで知能を持つようにするためには、決定的にかけていることがあります。それは、人の脳(脳細胞)は、外部からの刺激により動的に構築されていきますが、プログラムでは動的にプログラムを拡張できません。
動的に拡張するようにプログラムを組むことはできますが、それは決められたプログラムの組み合わせ方を変えているに過ぎません。
逆に言えば、そこが解決すれば、脳と同じような成長するプログラム(=AI?)ができると思います。
蛇足が長くなってしまいました。
関数型言語にしても、この特性を理解してプログラムしなければ、オブジェクト指向と同じ道をたどることになります。
オブジェクト指向と関数型言語は、プログラムに対する見方を変えただけで、画期的な新しいパラダイムではなく、昔からあるパラダイムの一つでしかなく、目的を実現するためのツールです。
ひとつのツールに集約するのではなく、目的のために複数のツールを使って実現すると言うのが正しいと、自分は考えます。
また、ツールを使うのが目的ではなく、目的を達成するためにツールを使うのです。
その為には、ツールの本質を理解することが、重要だと思います。