宣言型プログラミング

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

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

宣言型プログラミング: Declarative programming)は過程ではなく対象を定義してプログラムを構成するプログラミングパラダイムである[1]

概要[編集]

宣言型プログラミングでは対象の定義 =「何(What)を得たいか」を宣言してプログラムを構成し、逆にそれを得る過程・手続き・アルゴリズム =「どうやって(How)得るか」を記述しない[1][2]。すなわち、出力を得る方法ではなく、出力の性質・あるべき状態を記述することが「宣言型」である。

例えば「朝ごはん」をプログラムする。やり方の1つは食べたいもの =「メニュー」を宣言する方法である。もう1つは調理過程 =「レシピ」を記述する方法である。レシピが一切わからなくても結果として作られる朝ごはんを定義することはできるし、逆に何ができるかわからなくてもとにかく1つ1つの調理作業を記述することでも朝ごはんはプログラムできる。宣言型プログラミングは前者すなわちメニューを宣言するスタイル(= プログラミングパラダイム)である。

プログラミング言語の場合、宣言型プログラミング言語であるSQLのクエリは「どのようなデータが欲しいか」を宣言し、どのテーブルから先に見るかなどといった「いかにしてデータベースにアクセスするか」という命令・手続きには関与しない。この手法はFORTRANC言語Java等の命令型プログラミング言語とは全く異なる。命令型では、目的を実現するアルゴリズムを、その順序に沿う形で記述する。このように命令型プログラミングは目的の達成方法を「手続き」として示し、宣言型プログラミングは達成目的(出力)を示して、その実現手続きは処理系・ランタイム・フレームワーク等に委譲する。

宣言型プログラミングは得るものを宣言する。これに起因した宣言型プログラミングの特徴がある。

  • 参照透過性: 同じ引数ならば常に同じ出力を返す[3](得るもの = 出力を定義するスタイルなので出力は揺るがない)
    • 独立
    • 状態を持たない
    • 決定的

宣言型プログラミングのもつ性質は他の様々なプログラミングパラダイムでも見られる。例えば関数型プログラミング論理プログラミング制約プログラミングが挙げられる。これらは数理論理学に基づいて設計されたプログラミング言語であり、命令型言語と対立する概念である。関数型言語ならラムダ計算コンビネータ論理代数学などと対応し、論理プログラミングならその式はホーン節に対応する。制約プログラミングや論理プログラミングでは解の性質のみを記述し解を求めるアルゴリズムは指定しないこともある。命令型言語で宣言型プログラミングを行う場合、手続き的な詳細をカプセル化する。例えば単体テストフレームワークJUnitではリフレクションが用いられる。

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

利点[編集]

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

  • 結果を得る過程の抽象化[4]: 宣言側の簡略化、内部実装側の最適化
  • 状態の分離: 宣言部分の出力を予測するために状態履歴とそれを起こすコードを探る必要が無くなる[5][6]

手続きの最適化[編集]

宣言型プログラミングは対象(What)を宣言により抽象化し手続き(How)と分離する。分離された手続きはランタイム等の内部実装によって処理される。ゆえに宣言型プログラミングではプログラムへ影響を与えずに手続きを最適化できる。

例えば宣言的UIで宣言が更新された際、全てのUI要素を再描画するのがもっとも単純な内部実装になる。しかし内部で宣言を保持しておき更新時に差分を得てその部分のみ更新すること(差分更新)でパフォーマンスを最適化できる[7]。宣言型プログラミングをおこなっているUIプログラマー目線ではこれは内部実装の最適化であり、UIプログラム自体には一切の変更が必要ない。

このように手続きが内部へ隠蔽される特性のおかげで、宣言型プログラミングは手続きの最適化を容易に行える。

状態の分離[編集]

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

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

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

[編集]

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

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

  • XSLT は、XML文書の変換のためのチューリング完全な宣言型言語
  • SQL は、関係データベースのクエリのための宣言的要素を持つ。チューリング完全。
  • Nix Expression Language
  • Dhall

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

利用される局面

脚注[編集]

[脚注の使い方]
  1. ^ a b "what declarative programming is. Intuitively, it is programming by defining the what (the results we want to achieve) without explaining the how (the algorithms, etc., needed to achieve the results). " P. Van Roy and S. Haridi (2001). コンピュータプログラミングの概念・技法・モデル. p.117.
  2. ^ 「宣言的記述を行う高水準言語の主要なお題目は『どうやって計算するか(How)ではなく, 何を計算するか(What)を記述する』というものである.」 Chikayama (2014). Software: Thirty Past Years and the Futures. コンピュータソフトウェア, Vol.31, No.2, p.9.
  3. ^ "We say the operation is declarative if, whenever called with the same arguments, it returns the same results independent of any other computation state." P. Van Roy and S. Haridi (2001). コンピュータプログラミングの概念・技法・モデル. p.113.
  4. ^ "programming concept where an ideal ... representation ... is kept in memory and synced with the “real” DOM by a library ... This approach enables the declarative API ... : You tell React what state you want the UI to be in, and it makes sure the DOM matches that state. This abstracts out the attribute manipulation, event handling ..." React. Virtual DOM and Internals.
  5. ^ 時間軸と何が起きたかを意識せずに宣言的に記述できる sonatard. (2019) 宣言的UI. p.37
  6. ^ "React provides a declarative API so that you don’t have to worry about exactly what changes on every update." React. Reconciliation.
  7. ^ "declarative UI ... works by conceptually regenerating the entire screen from scratch, then applying only the necessary changes." Thinking in Compose. Jetpack Compose.
  8. ^ 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)"
  9. ^ 前回のViewの状態に依存せずに、最終的に描画されるViewを宣言的に記述できる sonatard. (2019) 宣言的UI. p.37

参考文献[編集]

関連項目[編集]