プログラミングパラダイムについてまとめる

# はじめに
**プログラミングパラダイム**について整理する。

# プログラミングパラダイムとは
プログラミングパラダイムとは、プログラムのスタイル、または「方法」のことである。
ほぼ全てのプログラミング言語は、何らかの概念や考え方をベースに作られており、その概念や考え方を**パラダイム(Paradigm)**と言う。
パラダイムは相互に排他的なものではなく、1つのプログラムに対して、複数のパラダイムが存在することもある。また、プログラミング言語によっては、あるパラダイムでは簡単に書けても他のパラダイムでは簡単には書けないものも存在する。

# プログラミングパラダイムの種類
以下のようなプログラミングパラダイムが存在する。

```
- 命令型プログラミング
- 宣言型プログラミング
- 構造化プログラミング
- 手続き型プログラミング
- 関数型プログラミング
- コンビネータ論理（Function-Level (Combinator)）
- オブジェクト指向プログラミング
    - クラスベース
    - プロトタイプベース
- イベント駆動プログラミング
- フロー駆動型プログラミング
- ルールベースプログラミング
- 制約プログラミング
- アスペクト指向プログラミング
- リフレクティブプログラミング
- 配列プログラミング
```

# 各プログラミングパラダイムの詳細
全ての詳細まで理解できていないため、現時点で理解できている範囲で記載する。
今後整理できたタイミングで追記していく。

## 命令型プログラミング
グローバルな状態(state)を更新する、一連の命令によるプログラミング。
（乞うご期待）

## 宣言型プログラミング
（乞うご期待）

## 構造化プログラミング
1967年にEdsger W.Dijkstra氏が発表した論文『[構造化プログラミング(Structured Programming)](https://dl.acm.org/doi/pdf/10.5555/1243380)』が考え方の基となっている。この論文は、1つの入口と1つの出口を持つプログラムは、順次・分岐・反復という3つの論理構造によって記述できるという「構造化定理」を証明したものである。
つまり、**順次・分岐・反復という3つの論理構造を持ったプログラムを作成する**手法のことを指す。

```
- 順次
    - コンピュータに対する命令を上から順に実行させること
- 分岐
    - 条件によって処理を切り替えること
    - if文やcase文を使った制御構造が相当する
- 反復
    - 一定回数あるいは条件を満たす間、ひとまとまりの処理を繰り返し実行すること
    - for文やwhile文を使った制御構造が相当する
```
この基本の3つの構造は、現在普及しているプログラミング言語の多くがサポートしている。

## 手続き型プログラミング
**「手続き」を呼び出すことでプログラムを作成する**手法である。
この手続きとは、例えば、C言語なら「関数」、Perlなら「サブルーチン」などのようにプログラミング言語によって異なる。
メインの手続きを、プログラムの起点から呼び出し、その手続きから別の手続きが呼び出され、と各手続きが繰り返されて、メインの手続きの処理を全て実行するとプログラムは終了する。
手続き型プログラミングでは、手続きという単位でプログラムを構造化できるため、処理の流れを把握しやすく見通しの良いプログラムを作成できる。

## 関数型プログラミング
**関数を処理の単位としてプログラムを作成するする**手法である。
関数型プログラミングには以下の3つの特徴がある。

```
- 純粋関数
    - 引数(入力)の値が決まると、戻り値(出力)が一意に決まる関数であること
    - 出力が入力に依存するため、引数と戻り値が必須となる
- 参照透過性
    - 引数が同じならば、戻り値は常に同じになる（副作用を持たない）
    - （オブジェクト指向プログラミングでは、オブジェクトの状態を保持する変数によって、戻り値が変化することがある）
- 遅延評価
    - 評価(計算)の指示が出ていても待機して、処理を遅らせることができる
        - 評価の指示はされているが、まだ行われていない状態を「プロミス」と呼ぶ
        - 実際に評価することを「サンク」と呼ぶ
```
これら特徴を持つことから、関数型プログラミングはデバックやテストが行いやすく、モジュール化やライブラリ化がしやすいとされている。
関数型プログラミングをサポートする言語には、Haskell、Scalaなどがある。

## コンビネータ論理（Function-Level (Combinator)）
変数を一切使わないプログラミング。
（乞うご期待）

## オブジェクト指向プログラミング
構造化プログラミングでは、1から全てのプログラムを作成する必要があり、できるだけ既存のプログラムを部品化して再利用したい、という背景があり、考案されたのがオブジェクト指向プログラミングとされている。
オブジェクト指向に明確な定義はないが、プログラムをオブジェクト同士のやり取りによって表現し、**データ自身に自分をどうするのか任せ、データを中心にプログラムを作成する**というのが基本的な考え方である。
それぞれのオブジェクトに、属性（データ）と振る舞い（処理）を持たせ、オブジェクト同士のやりとりを通じて全体の処理を進めていく。
また、オブジェクト指向の三大機能として、「カプセル化」「継承」「ポリモーフィズム」と呼ばれるものがある。ただし、この3つの機能がない言語でも、オブジェクト指向言語と呼ばれることもある。

## イベント駆動プログラミング
イベント駆動とは、プログラム実行中に何らかのイベント(出来事)が発生した時に、対応する処理を自動的に呼び出して実行する仕組みのことである。例えば、「ボタンがマウスでクリックされた」、「キー入力が行われた」などがイベントの例である。
つまり、イベント駆動プログラミングとは、**イベント駆動の仕組みを使ってプログラムを作成する**手法である。
上記のようなイベントの例を、手続き型プログラミングをサポートする言語でプログラムを作成しようとすると、常にイベントを監視し、イベントが発生すれば速やかにメッセージを表示する処理を実行するプログラムを書く必要があるが、イベント駆動プログラミングでは、イベントが発生した時のプログラムを書くだけで済む。
しかし、イベントが発生すると突如として処理が始まるため、プログラムの規模が大きくなると、処理全体の流れを把握しにくくなる欠点がある。

## フロー駆動型プログラミング
（乞うご期待）

## ルールベースプログラミング
（乞うご期待）

## 制約プログラミング
（乞うご期待）

## アスペクト指向プログラミング
（乞うご期待）

## リフレクティブプログラミング
（乞うご期待）

## 配列プログラミング
強力な配列演算子を用いたプログラミングで、通常はループを必要としない。
（乞うご期待）


# 参考資料
* [Programming Paradigms](https://cs.lmu.edu/~ray/notes/paradigms/)
* [図でわかるプログラミング用語事典（日経BP-Next-ICT選書）](https://amzn.to/3hIPFHL)