「関数型プログラミング」の版間の差分

削除された内容 追加された内容
編集の要約なし
(同じ利用者による、間の5版が非表示)
1行目:
{{独自研究|date=2014年4月}}
{{プログラミング言語|index=かんすうかたけんこ}}
[[ファイル:Orange lambda.svg|境界|右|フレームなし|167x167px|代替文=]]
'''関数型言語'''(かんすうがたげんご、{{lang-en-short|functional language}})は、以下に述べる'''関数型プログラミング'''を基本スタイルとして推奨する機能を持つ[[プログラミング言語]]、関数型プログラミング言語<ref>{{lang-en-short|functional programming language}}</ref>の略称である。
'''関数型プログラミング'''(かんすうがたプログラミング、{{lang-en-short|''functional programming''}})は、[[プログラミングパラダイム]]の一つであり、[[ソフトウェア工学]]における主にプログラムリスト作成とコード記述の分野で用いられる考え方である。一説には[[数理論理学]]の[[ラムダ計算]]をモデルにして考案されたと言われる。
 
プログラムの基本要素である値(''value'')を限りなく抽象化して、入力と出力の同時表現体にすると共にその変換式も併せ持たせたものが、ターム的に'''関数'''(''function'')と定義されている。関数は同時にパラメータ値とリターン値にも出来るので変換式の連鎖が可能である。変換式(コード)はプログラム環境(データ)に一切の影響を与えず、また一切の影響を受けない事が保証されている。プログラム環境に影響を与えるコードは一般の関数と慎重に区別される。このコードとデータを完全に分離する設計が関数型プログラミングの大きな特徴である。
== 関数型プログラミング ==
何をもって関数型プログラミングとするか、ということに関して、関数型プログラミングのコミュニティ内でも正確な定義や合意というものは存在しない。したがって関数型言語の定義も明確な境界はない。ただし、[[手続き型プログラミング]]が命令実行の列としてプログラムを記述していくのに対し、関数型プログラミングは複数の式を関数の適用によって組み合わせていくプログラミングスタイルである<ref name="faq">{{cite web | url = http://www.cs.nott.ac.uk/~gmh/faq.html | title = Frequently Asked Questions for comp.lang.functional | accessdate = May 14, 2015}}</ref>。手続き型プログラミングの発端は計算機の命令 (instruction/command) や構造に密接にかかわりがある一方、関数型プログラミングは数学の理論を発端としている。
 
プログラムは値の宣言(''declaration'')とそれらを演算子で繋いだ式(''expression'')の連続で構成され、これが順次処理となる。値は数値、構造体、関数、関数連鎖として随時抽象化される。分岐処理は条件式とthen式とelse式を合わせた式の一形態で行なわれる事が多い。反復処理は関数の[[再帰]](''recursion'')として行なわれ、その関数内の評価(''eval'')が変わらなくなるまで繰り返される。関数型プログラミングの流れはこの様なものである。
 
== 特徴 ==
何をもって関数型プログラミングとするか、ということに関して、関数型プログラミングのコミュニティ内でも正確な定義や合意というものは存在しない。したがって関数型言語の定義も明確な境界はない。ただし、[[手続き型プログラミング]]が命令実行の列としてプログラムを記述していくのに対し、関数型プログラミングは複数の式を関数の適用によって組み合わせていくプログラミングスタイルである<ref name="faq">{{cite web | url = http://www.cs.nott.ac.uk/~gmh/faq.html | title = Frequently Asked Questions for comp.lang.functional | accessdate = May 14, 2015}}</ref>。手続き型プログラミングの発端は計算機の命令 (instruction/command) や構造に密接にかかわりがある一方、関数型プログラミングは数学の理論を発端としている。
 
==== 第一級関数と高階関数 ====
 
==== 純粋関数 ====
 
==== 再帰 ====
たとえば、1 から 10 までの整数を足し合わせるプログラムを考える<ref>本来は[[等差数列]]の和の公式を用いて定数時間で問題を解く方法が最適解だが、ここではプログラミングスタイルの比較のため数値計算的手法を用いる。</ref>とき、手続き型プログラミングでは以下のように[[ループ (プログラミング)|ループ]]文を使って一時変数に数値を足していく(一時変数の内容を書き換える)命令を繰り返し実行するという形を取る。
 
39 ⟶ 49行目:
ただし再帰呼び出しは[[スタックオーバーフロー]]の危険性やオーバーヘッドを伴うため、注意深く使用しなければならない<ref>[https://msdn.microsoft.com/ja-jp/library/dd233229(v=vs.120).aspx 関数 (F#) | MSDN]</ref>。通例、関数型言語では、[[末尾再帰]]呼び出し (tail-recursive call) の形で書かれた関数をループに展開する[[コンパイラ最適化]]により、スタックオーバーフローの危険性および再帰のオーバーヘッドを解消する。[[Scheme]]など、関数型言語の中には末尾再帰呼び出しの最適化を仕様で保証するものもある。
 
==== 厳格評価と遅延評価 ====
また、関数型言語は文 (statement) よりも式 (expression) を中心とした言語仕様となっていることも特徴である。前述の例において、再帰関数<code>sum</code>を[[束縛 (情報工学)|束縛]]する<code>let</code>は式である。また、条件分岐の<code>if-then-else</code>も式である。文よりも式で書けることが多いほうが都合がよい。
 
==== 型推論 ====
関数型言語は関数型プログラミングをサポートする言語ではあるが、手続き型プログラミングを行なうことも可能である。例えばF#では以下のようなPascal風の書き方もできる。
 
<source lang="fsharp">
==== 参照透過性 ====
let mutable total = 0
for i = 1 to 10 do
total <- total + i
printfn "%d" total
</source>
 
==== データ構造体 ====
ただし[[Haskell]]のようにループ構文をサポートせず、従来の手続き型プログラミングが難しいケースもある。
 
==== ファンクタ、モナド、アプリカティブ ====
逆に手続き型言語を使って関数型プログラミングを行なうことも可能であるが、末尾再帰呼び出しの最適化がサポートされるかどうかはコンパイラ次第である。
 
== 概要 ==
83 ⟶ 89行目:
21世紀に入ると、[[Java仮想マシン|{{lang|en|Java}}仮想マシン]]や[[共通言語基盤]]({{lang|en|CLI}})をランタイムとする関数型プログラミング言語を実装しようという動きが現れ、{{lang|en|[[Scala]]}}・{{lang|en|[[Clojure]]}}・{{lang|en|[[F Sharp|F#]]}}などが登場した。
 
== 代表的な関数型プログラミング言語一覧 ==
{|class="wikitable sortable"
!言語
124 ⟶ 130行目:
従来の手続き型と分類されるプログラミング言語においても、関数型プログラミングを行ないやすくなる機能を備えているものもある。[[C言語]]および[[C++]]は[[関数へのポインタ]]をサポートし、関数をオブジェクトのように扱うことができるが、関数ポインタによって[[第一級関数]]をサポートしているとみなされてはいない。なお、C# 3.0、[[C++11]]、Java 8など、後発の規格においてラムダ式([[無名関数]])をサポートするようになった言語もある。
 
=== '''その他の関数型プログラミング的性質を持つ言語 ==='''
 
* {{lang|en|[[APL]]}}
* {{lang|en|[[XSL Transformations|XSLT]]}}