手続き型プログラミング

出典: フリー百科事典『ウィキペディア(Wikipedia)』

出典: フリー百科事典『ウィキペディア(Wikipedia)』
検索に移動
Процесс решения задачи проектирования.png

手続き型プログラミング(てつづきがたプログラミング、: Procedural programming)は、手続きの定義と呼び出しをプログラム全体を組み立てる土台にしたプログラミングパラダイムである。手続きは言語によってサブルーチン、関数、副プログラムとも呼ばれている。手続きはプログラム全体を区分けした部分プログラムでもあり、一定量の計算ステップまたは命令コードのまとまりを、任意の定義名に結び付けて識別化したコードユニットである。手続き型プログラミングは命令型プログラミングの分類に属しており、1958年のFORTRANⅡALGOLCOBOLといった最も初期の高水準言語から導入されている。

手続きprocedure)はプログラム内のあらゆるポイントから呼び出す(call)ことができる。手続き内の終端位置に達した時は、その呼び出しポイントの次の命令コードに復帰(return)される。途中位置からでも復帰できる。手続きの呼び出しと復帰はコンピュータ側が提供するコールスタック機能によって実現されている。

特徴[編集]

手続き型プログラミングでは基本的に、起点になるメインルーチンをルートにして階層的に分割された無数の手続きと、全ての手続きから参照可能なグローバル変数集合といったプログラム構成になる。グローバル変数集合を任意のスコープで区分けできる言語もある。スコープは変数の可視性範囲である。複数の手続きから参照されるあらゆるデータをグローバルスコープにまとめてしまう簡素な設計は、プログラム全体への理解をむしろ促進するものとして小中規模のソフトウェア開発には適したものとされている。

手続きとは[編集]

手続きprocedure)は、命令コード(instruction code)のまとまりをパラメータリスト付きの識別子に結び付けたコードユニットである。プログラム起点のメインルーチンは手続きとは見なされない。識別子がリターン値の代入対象になる。これは全言語共通の見解である。COBOLでは副プログラムが手続き相当であり、副プログラムの命令コード記述部分を手続き部と呼んだ。FORTRANではリターン値を持たない方の手続きをサブルーチン、持つ方の手続きを関数と呼んだ。ALGOLではどちらも手続きと呼び、C言語ではどちらも関数と呼んだ。Pascalではリターン値を持たない方を手続き、持つ方を関数とした。なお、FORTRANのサブルーチンはその内部サブルーチンを複数記述可能で双方をまとめたものを外部手続き(邦訳は外部副プログラム)と定義している。

手続きの識別子は手続き名と呼ばれる。パラメータリストには任意の個数の引数が列挙される。引数無しのケースもある。手続き名+パラメータリストの次にコードブロックが置かれる。コードブロックには1行以上の命令コードが列記される。命令コードは引数の使用によってプロセスの多相性を実現できる。コードブロックはレキシカルスコープの範囲になり、そのスコープ専用のローカル変数を定義できる。ローカル変数は静的変数と自動変数に分かれる。静的変数はプログラム実行中を通して代入値が保持される。自動変数はスタックフレームを利用したもので、手続き内へのエントリと共に自動確保され、リターンと共に自動消去されるものである。命令コード行の終端に達するとリターンする。リターンとはその手続きの呼び出しポイントの次の命令行に移動することであり、任意のリターン値を呼び出し元に渡すこともできる。リターン命令で途中位置からのリターンもできる。スタックフレームの利用により手続きは再帰呼び出しも可能である。

手続き型プログラムの構造[編集]

手続き型プログラムは、メインルーチンをルートにして階層的に分割された無数の手続きと、全ての手続きまたは複数の手続きから参照可能なグローバル変数集合によって構成される。プログラムのコードは手続き単位に分割される。プログラムのデータはまずグローバル変数とローカル変数に大別され、ローカル変数の方は各手続きのスコープ内に分散される。グローバル変数スコープには、それぞれの手続きないし手続きグループから参照される様々な変数がまとめて雑然と置かれることになる。言語によってはグローバル変数を任意のスコープで区分けできる機能を備えており、特定の手続き群だけが参照できるグローバル変数の定義を可能にしている。これが無い言語では、コンパイラやインタプリタによるスコープ違反(可視性違反)のチェックを受けられないので、特定のグローバル変数を特定の手続き専用にするといったモジュール性に向けた設計はプログラマの裁量に委ねられる事になる。一般に手続き型プログラミングの長所は平易性と明解性、短所は堅牢性と保守性とされている。

命令型プログラミング[編集]

手続き型は命令型プログラミングの分類に属している。これが意味する主なプログラム上の枠組みは、手続きはパラメータ無しでもよくリターン値がなくてもよい、手続き内ではグローバル変数とローカル静的変数が自由に更新される、手続きは渡されたパラメータ以外の情報要素の影響を無制限に受ける、の三点になる。

歴史[編集]

手続き(procedure)の考え方自体はコンピュータ黎明期の機械語コードの時代から存在している。手続きの実装方式は、アセンブラなどの低水準言語で用いられるニーモニックコードのCALL命令とRET命令が原点である。PUSH命令による引数のスタックメモリへの積み込みと、スタックポインタレジスタの減算による自動変数領域の確保、ベースポインタレジスタによる引数と自動変数の参照といったスタックフレームの機能もアセンブラ由来のものである。CALL命令のジャンプ先アドレスに付けられたラベルは手続き名と同義になった。

その仕組みは1950年代半ばから登場した高水準言語にもそのまま受け継がれた。ラベルは形式化されたパラメータリスト付きのプロシージャネームになり、スタックフレーム処理も自動化され、命令コード行のかたまりはソースコード上で明確に区分けされたコードブロックとして形式化された。こうして手続き(プロシージャ)は低水準言語から高水準言語への移行期に言わばごく自然に誕生している。

他のパラダイムとの対比[編集]

オブジェクト指向プログラミング[編集]

同じ命令型プログラミングの分類に属しているオブジェクト指向は、手続き型の系譜に沿った発展形と見なせるものである。オブジェクト指向では変数と手続きを共にクラスに所属させて管理する。クラスは変数と手続きをひとまとめにしたものである。プログラム内の全ての変数と手続きはクラスによってグループ化される。このグループ化はモジュール化と同義である。クラスは基本的にカプセル化されるので、決められた変数と手続き以外は他のクラスから参照できなくなる。変数と手続きを共にまとめてモジュール化とカプセル化を実現するクラスの存在が、手続き型との大きな相違点である。クラスは継承多態性を始めとする様々な機能の表現にも用いられて更なるパラダイム拡張の土台になっている。

オブジェクト指向 手続き型
クラス モジュール
インスタンス 構造体
メソッド 手続き
データメンバ 変数

関数型プログラミング[編集]

関数型宣言型プログラミングの分類に属しているので設計と構文ともに数々の相違点が存在する。ここでは手続きに対する関数と、ステートメントに対する式といった代表的な二点について述べる。代数的データ型や束縛変数にこだわらないで普通の構造体や変数を用いている関数型言語も多いからである。

関数は他の関数に渡すための引数値にできる。また関数を返り値として返すこともできる。この高階関数と第一級関数の仕組みによる数々の機能は、手続きでは不可能である。FORTRANの外部関数、ALGOLの名前渡し、C言語の関数ポインタ渡しなどは高階関数らしく見えるが、本質的に異なるものである。その詳細はここでは割愛する。加えて関数は引数欄を埋める途中で保留できるのと、引数欄を全部埋めても評価しないで保留できる機能も持つ。評価とは手続きの呼び出し実行と同義である。関数型言語は評価前の関数と、評価後の関数を分けて表現できる機能を標準的に備えている。手続き型言語ではFORTRANとALGOLがそれに該当する引数の名前渡し機能を備えていたが、その後の多くの手続き型言語では採用されていない。名前渡し、シンボル型、遅延評価といったプログラム概念は手続き型には沿わないものと認識されるようになったからである。

プログラムの基本文にも違いがある。関数型の式はそれ自体が値と見なされるのに対し、手続き型のステートメントは命令コードと見なされる。式はシンボルを示すビット列と数値を示すビット列をそれぞれメモリ上に展開したまま保留させるという数学の数式をなぞったプログラム概念である。シンボルは関数、演算子、変数の識別子である。式は好きな時に簡約できるので値と同義になり、様々な応用を可能にする。ステートメントはCPUが解釈する命令コードそのものであり、CPU解釈の過程で最後に変化したレジスタないしメモリのビット列が値になる。その値は命令コード通過後の残り物でしかないので応用不可である。

関数型 手続き型
ステートメント
関数 手続き
代数的データ型 基本型構造体
束縛変数と自由変数 変数

論理型プログラミング[編集]

論理型宣言型プログラミングの分類に属している上にコードスタイルも論理式に則っているので、手続き型とは設計と構文ともに大きな違いがある。論理型ではホーン節の集合が手続きに当たるものになる。論理型ではgoto文を完全に廃した構造化定理さながらに、リテラルの並びによる順次、リテラル証明とバックトラックとカットオペレータを利用した選択、リテラル証明の再帰による反復といった三つの制御構造でプログラムは組み立てられる。この事はコードブロック単位の条件分岐や単純なループ文およびgoto文を普通に使える手続き型よりも、コーディング難易度を上げる一因になっている。

論理型 手続き型
ホーン集合 手続き
ファクト 手続きプロトタイプ
正格ホーン節 手続き実装内容
リテラル ステートメント

代表的な手続き型言語[編集]

手続き型プログラミングは、1958年公開のFORTRANⅡCOBOLALGOLといった最も初期の高水準言語から導入されている。1980年代に入るとほとんどの手続き型言語はマルチパラダイム化した。その代表的な発展形はオブジェクト指向プログラミングである。手続き型プログラミングはあまりにも基本的なパラダイムゆえにそれ単体としての存在感を失い、オブジェクト指向その他の前段階といった認識で扱われるようになっている。

関連項目[編集]