宣言型プログラミング

宣言型プログラミング: Declarative programming)は、対象の性質を宣言してプログラムを構成するプログラミングパラダイム、あるいはそのような性質をもったプログラミングパラダイムの総称である。

総称としての宣言型プログラミングは関数型プログラミング論理プログラミング制約プログラミングを含む。これらのプログラミングパラダイムは対象を宣言する性質を共有した特徴として持つ。命令型プログラミングCPUOSへの命令列と言えるが、例えばLISPもコンピュータへの命令列かもしれないが、その理論的基盤は間違いなくラムダ計算である。そこでこちらでは、その生い立ちや理論的基盤を考慮して分類することにする。

概要編集

宣言型プログラミングは「対象の性質を宣言してプログラムを構成する」ことで特徴づけられる。すなわち、出力を得る方法ではなく、出力の性質・あるべき状態を記述することを「宣言型」と称する。

一例として宣言型プログラミング言語であるSQLのクエリは「どのようなデータが欲しいか」を宣言しており、B木の操作などといった「いかにしてデータベースにアクセスするか」という命令・手続きには関与しない。この手法はFORTRANC言語Java等の命令型プログラミング言語とは全く異なる。命令型では、目的を実現するアルゴリズムを、その順序に沿う形で記述する。つまり、命令型プログラムでは目的を達成するための方法を「手続き」として示すのに対し、宣言型プログラムでは達成すべき目的(出力)を示して、それを実現する手続きはシステム(処理系・ランタイム・フレームワークなど)に任せるわけである。

総称としての宣言型プログラミングは、関数型プログラミング論理プログラミング制約プログラミングの総称である。この立場での「宣言型プログラミング」とは、数理論理学に基づいて設計されたプログラミング言語のことであり、命令型言語と対立する概念である。関数型言語ならラムダ計算コンビネータ論理代数学などと対応し、論理プログラミングならその式はホーン節に対応する。

この2つの定義はある程度オーバーラップしている。特に制約プログラミングでは、解の性質を記述することに注力し、解を求めるためのアルゴリズムは特に指定しないこともある。論理プログラミングにもその傾向がある。とはいっても、制約プログラミング言語や論理プログラミング言語でもアルゴリズムや実装の詳細を記述することは可能ではある(可能であるということは、常にそのようなスタイルでプログラムを書くという意味ではないが)。

同様に命令型プログラミング言語であっても、プログラムを宣言型のスタイル・パラダイムで書くことは可能である。この場合、宣言的でない詳細をライブラリやフレームワークでカプセル化するのが一般的である。例えば、単体テストのフレームワークであるJUnitリフレクションを使ったスタイルがある。

宣言型のスタイルがよくあらわれる例にはドメイン固有言語 (DSL) がある。また冪等性が求められる箇所でもしばしば用いられる。なぜならあるべき状態の宣言は何度宣言しても同じ状態になる(冪等である)からである。

利点編集

宣言型プログラミングは以下の利点を持つ[1]

  • 状態の分離: 宣言部分の出力を予測するために状態履歴とそれを起こすコードを探る必要が無くなる

宣言型プログラミングでは宣言部分と状態を分離できる。なぜなら宣言部分ではあるべき状態を宣言するため、その前にどうなっていたかは無関係であるからである。例えば「廊下の電気はONである」と宣言した場合、現在の廊下の電気がONであれOFFであれ、(宣言された)なるべき状態はONであり、現在の状態とは無関係である。すなわち宣言型プログラミングでは時間と共にどう変わるか(=状態)を宣言部分で考える必要がなくなる[2]

もし命令型プログラミングを用いて「廊下のスイッチを押す」という命令をコーディングして廊下の電気を制御した場合、実行後の電気がONかOFFかは現在の値に依存する。ゆえに出力を予測するには状態の履歴を知っている必要がある。そして状態の履歴を知るためには、状態を操作しうる他のコードを把握し、その操作履歴を知る必要がある。ON/OFFの2状態ならまだしも、多数の状態が相互作用する多数のオブジェクトから操作される場合、状態の予測は著しく困難になり、デバッグを含めたプログラミングが難しくなりうる。一方で宣言型プログラミングの場合、宣言部分は状態履歴を必要としないため、宣言部分の出力は常に明確である。

注意点として、状態は分離されているのであり、状態が消滅したわけではない。宣言型プログラミングの場合、light変数にてあるべきライトの状態 "ON"/"OFF" を保持しておき、現在の時刻に基づいてlight変数を切り替え、それが「廊下の電気は{light}である」という宣言に反映されて実際に廊下の電気がONになるというような形になる。light変数という状態は存在しており、これが宣言部分と分離され、宣言部分は最新のlight変数が示す今の電気があるべき状態のみを反映した(過去の電気状態履歴とは無関係な)形になっている[3]。命令的プログラミングで問題となった予測の困難さは、light変数の履歴予測の困難さに分離されている。light変数を誰がいつ操作したかは依然として追跡の難しい問題であるが、宣言部分が分離されたことで問題の所在が限局したものになっている。

編集

宣言型プログラミング的側面を持つフレームワーク:

宣言型プログラミングをサポートするドメイン固有言語:

宣言型プログラミングをサポートする関数型/論理型/制約型のプログラミング言語:

利用される局面

脚注編集

[脚注の使い方]
  1. ^ 時間軸と何が起きたかを意識せずに宣言的に記述できる sonatard. (2019) 宣言的UI. p.37
  2. ^ Here is the critical thing. We no longer need to think about how our UI changes over time. What happens is, when we get in the data, we show what it should look like. We show what the next state is. And then framework controls how to get from one state into the other. And so now we no longer need to think about it. And that's the critical piece. Leland Richardson (2019-10-24) "Understanding Compose (Android Dev Summit '19)"
  3. ^ 前回のViewの状態に依存せずに、最終的に描画されるViewを宣言的に記述できる sonatard. (2019) 宣言的UI. p.37

参考文献編集

関連項目編集

外部リンク編集