「宣言型プログラミング」の版間の差分
削除された内容 追加された内容
Baudanbau20 (会話 | 投稿記録) m "Template:" を含むテンプレート呼び出し |
編集の要約なし |
||
(同じ利用者による、間の17版が非表示) | |||
1行目:
[[ファイル:DFAexample.svg|境界|右|フレームなし|265x265ピクセル]]
{{プログラミング・パラダイム}}
'''宣言型プログラミング'''({{lang-en-short|''Declarative programming''}})は、総称的に用いられる[[プログラミングパラダイム]]であり、[[プログラミング言語]]および[[プログラミングパラダイム|パラダイム間]]の分類用語として使われることが多い。対義語である[[命令型プログラミング]]との対比概念としてよく用いられる。宣言型は[[プログラミング|プログラミング理論]]のバックボーンである[[数学]]および[[形式論理学]]の性質に準拠したものであり、[[オートマトン|オートマタ理論]]的には[[チューリングマシン|決定性チューリングマシン]]に沿っている。前提と結論、定義と推論、問題と解答、条件と結果、入力と出力などが時系列に関係なく正確に対応して例外なく明示されており、その触媒となる作用、写像、演算などは原則として[[冪等]]であり、それに対する入力要素と出力要素が不可欠になっているという性質を指して宣言的(''declarative'')または平叙的(''declarative'')と言われる。
概略すると「一つの[[トランザクション]]または一つの[[プログラム (コンピュータ)|プログラム]]実行枠内でのあらゆるオペレーションにおいて、その遷移作用原因になる全情報要素と全環境状態をオペレーションのインプットに内包し、その遷移作用結果になった全情報要素と全環境状態をオペレーションのアウトプットに内包して、遷移作用の法則が不変になっている」というプロセス全般または作業全般を指して宣言的と言われる。遷移作用(''transition function'')の[[冪等|冪等性]]によるインプットとアウトプットの対偶関係は[[参照透過性]]を表わす。サブルーチン処理内容に重点を置いている命令型に対して、宣言型は引数と返り値に焦点を当てているとも言える。
== 概要 ==▼
宣言型プログラミングは、プログラミング言語のための分類用語としての性格が強い総称的なプログラミングパラダイムなので、どうしてそのような分類が必要になったのかという視点から解釈するのが理解への早道になる。宣言型と命令型という二大分類が定義された背景には、数学や[[形式論理学]]([[数理論理学]])をバックボーンにしたコンピュータ原理とプログラミング言語理論の成立過程がある。あらゆる問題への解法において、数学や[[形式論理学]]の性質を引き継いでいる従来の方式が宣言型であり、[[計算機科学]]が持つようになった特有の方式が命令型である。宣言型は問題と解答の二者限定の平叙な関係の計算であるのに対して、その関係に状態(''state'')というものが加えられた計算の方は命令型となった。”状態”は問題内で宣言されていない潜在要素であり、命令型の計算は同じ問題でもその時の”状態”によって解答が変化した。計算過程による”状態”の変動とそれによる後続計算への影響は[[副作用 (プログラム)|副作用]]と呼ばれる。”状態”の影響が無い平叙な計算と、”状態”に影響される手続き的な計算はコンピュータ計算性質の根本的な分かれ目になったので、前者の宣言型と後者の命令型というプログラミング理論上の二大分類が生まれた。
[[オートマトン|オートマタ理論]]的には、計算は遷移関数(''transition function'')、問題は入力値、解答は出力値、状態は遷移関数の[[非決定性チューリングマシン|非決定性]]に読み替えられる。プログラム的には、計算はサブルーチン、問題は引数、解答は返り値、状態はサブルーチン内外の静的メモリデータに読み替えられる。状態による計算の複雑性の拡充は、[[ノイマン型]]のコンピュータ機構に適したものだったので[[機械語]]と[[低水準言語]]([[アセンブリ言語|アセンブラ]])はその必要性から命令型で構築された。また最初期の[[高水準言語]]([[FORTRAN]]、[[COBOL]]、[[ALGOL]])も[[ノイマン型]]の性質に適した命令型になった。1950年代半ばからの高水準言語の普及につれて、命令型が利点的に拡充した計算の複雑性が今度は問題として挙げられるようになり、1960年代になると数学への原点回帰とも言える宣言型がその解決策として注目され始めた。また[[並行計算]]と宣言型の適性も認識され始めた。1970年代になると宣言型は非ノイマン型コンピュータ構築のためのパラダイムとしても重視されるようになった。
[[FORTRAN]]、[[ALGOL]]、[[COBOL]]といった[[命令型プログラミング|命令型]](''imperative'')[[高水準言語]]が公開されていく中で、1958年に初回発表された「[[LISP]]」が宣言型(''declarative'')高水準言語の元祖と見なされている。LISPは[[自動推論]]、[[自然言語処理]]、[[自動定理証明]]、[[人工知能]]研究といった目的で使われたが、当時の数学者の視点では命令的=手続き的(''procedural'')な言語と解釈されていた。式[[再帰]]の多用による[[複雑系]]のアルゴリズムがもはや平叙的(''declarative'')ではないと見なされたからである。1960年代から[[メインフレーム]]上の[[並行計算]][[データフロープログラミング|データフロープログラム]]が普及しそのための[[低水準言語]]はより平叙的な性質を示していた。また[[述語論理]]を基礎にした[[論理プログラミング]]の研究も始まりその中で実装された数々の言語もより平叙的な性質を持っていたが、1969年稼働の「[[Planner]]」は手続き的性質を備えていた。1964年公開の動的型付け関数型言語「[[APL]]」は平叙的であったが、LISPを原点にした60年代の[[関数型プログラミング]]は概ね手続き的性質に寛容だった。1970年代になると平叙的な静的型付け関数型言語「[[ML (プログラミング言語)|ML]]」と純粋関数型の先駆である「SASL」が公開され、1977年発表の関数水準言語「[[FP (プログラミング言語)|FP]]」は明確な平叙的=宣言型を旨としていた。これを発表した[[ジョン・バッカス]]([[FORTRAN]]開発者)は、関数型スタイルを従来の[[ノイマン型コンピュータ]]からの脱却と飛躍に結び付けた。命令型に対する宣言型というプログラミング理論構図が広まったのはこの頃からである。
== 特徴 ==
宣言型プログラミングとは端的に述べると、あらゆる遷移関数(''transition function'')において、状態遷移の原因になるあらゆる情報要素とあらゆる環境情報を遷移関数の引数に収納しており、状態遷移の結果になったあらゆる情報要素とあらゆる環境情報が遷移関数の返り値に収納されており、それら引数と返り値と遷移関数の整合性を維持するために、同じ引数に対する遷移関数の処理内容と返り値の一定化が保証されているというプロセス全般の構築を意味している。これらの仕様は主に[[参照透過性]]というプログラム概念に結び付けられている。これらの仕様を実現するための実装スタイルを箇条書きすると大抵は以下のようなものになる。
* '''関数'''へのパラメータ引数に状態遷移の原因になるあらゆる情報要素と環境要素が内包されており、同関数からのリターン値に状態遷移の結果になったあらゆる情報要素と環境要素が内包されている。
* 同じパラメータ引数に対する関数の処理内容は常に同一であり、そのリターン値も常に同一である。
* 関数の実行には原則的にパラメータ引数の入力を必要とする。入力の無い関数は上述の状態と副作用に依存した稼働方式になるからである。
* 実行された関数は原則的にリターン値の出力を要求される。出力の空白は次の関数への入力の喪失を意味するのでプロセス停止に繋がる。
*'''式'''をプログラムの基本単位とする。式は関数または演算子をノードにした入力と出力の連鎖体であり、式自体が最終出力値と同義になる。式は初期入力値を与えられて計算実行される。この計算実行は評価と呼ばれる。初期入力値は引数と呼ばれる。最終出力値は評価値と呼ばれる。
*初期入力値を与えられた式はその計算実行を保留する事もできる。その保留状態の式の任意時の計算実行は'''遅延評価'''と呼ばれる。
*保留状態の式を値として他の式の初期入力値にする事もできる。これは'''名前渡し'''と呼ばれる。保留状態の式は'''継続'''とも呼ばれる。
*数学上の性質から変数は再代入されない。この視点による変数への初期代入は変数への値の束縛と呼ばれる。この仕組みは'''束縛変数'''と呼ばれる。式の引数も束縛変数である。再代入禁止は'''不変性'''と言い換えられる。
*束縛変数に対する'''自由変数'''という概念がある。自由変数は(A)未束縛状態の変数、(B)式内で引数以外が束縛されている変数、(C)式内で再代入可能になっている変数など複数の意味がある。(A)はパターンマッチングで大きな意味を持つ。
宣言型プログラミングとは上述の関数の性質および式、遅延評価、名前渡し、継続、束縛変数、不変性、自由変数といった要点の用法に専念しているプログラミングである。別の言い方をすると命令型プログラミングでも上述の関数の性質と要点の用法に専念すれば、それは自ずと宣言型プログラミングになる。パラダイム間でこれらの性質を特に受け継いでいるのが、[[関数型プログラミング]]、[[論理プログラミング]]、[[データフロープログラミング]]などである。他にも[[制約プログラミング]]はそれだけで独立しているものではないが、[[全称量化子]]と個体の間に横たわるあらゆる中間状態を指した制約という情報要素を扱う性質から、必然的に宣言型における関数の性質と要点の用法に専念されていることが多い。関数は[[存在量化子]]と同義であり、制約も関数とは異なる形態の[[存在量化子]]なので、後者を扱うための前者は[[参照透過性|参照透過]]である方が都合がよいからである。
== 利点 ==
29 ⟶ 39行目:
注意点として、状態は分離されているのであり、状態が消滅したわけではない。宣言型プログラミングの場合、light変数にてあるべきライトの状態 "ON"/"OFF" を保持しておき、現在の時刻に基づいてlight変数を切り替え、それが「廊下の電気は{light}である」という宣言に反映されて実際に廊下の電気がONになるというような形になる。light変数という状態は存在しており、これが宣言部分と分離され、宣言部分は最新のlight変数が示す今の電気があるべき状態のみを反映した(過去の電気状態履歴とは無関係な)形になっている<ref>前回のViewの状態に依存せずに、最終的に描画されるViewを宣言的に記述できる [https://speakerdeck.com/sonatard/xuan-yan-de-ui?slide=37 sonatard. (2019) 宣言的UI. p.37]</ref>。命令的プログラミングで問題となった予測の困難さは、light変数の履歴予測の困難さに分離されている。light変数を誰がいつ操作したかは依然として追跡の難しい問題であるが、宣言部分が分離されたことで問題の所在が限局したものになっている。
== 脚注 ==
62 ⟶ 53行目:
== 関連項目 ==
*[[ドメイン固有言語]]
*[[マークアップ言語]]
▲**[[非手続き型言語]]
== 外部リンク ==
|