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

削除された内容 追加された内容
編集の要約なし
編集の要約なし
4行目:
 
== 関数型プログラミング ==
何をもって関数型プログラミングとするか、ということに関して、関数型プログラミングを行っているコミュニティ内でも正確な定義や合意というものは存在しない。したがって関数型言語の定義も明確な境界はない。ただし、[[手続き型プログラミング]]がコマンド命令実行の列としてプログラムを記述していくのに対し、関数型プログラミングは複数の式を関数の適用によって組み合わせていくプログラミングスタイルである<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 までの整数を足し合わせるプログラムは、以下のように一時変数に数値を足していくコマンド命令の繰返し実行という形を取る:
 
<source lang="pascal">
total := 0;
for i := 0 to 10 do
total := total + i;
done;
</source>
 
一方、関数型プログラミングでは、同じプログラムを一時変数を使わずに関数の再帰呼出しを使い、全体として一つの式として書くことができる:
 
<source lang="haskell">
let
sum x = if x == 0 then 0
else x + sum (x - 1)
in
sum 10
</source>
 
関数型言語は関数型プログラミングをしやサポート言語であるが、手続き型プログラミングを用いたプログラムを書く行なうこと可能である。
たとえば、C逆に手続き型言語は関数から成り立つ言語である。関数の中身は、を使って関数型プログラミングを行なうこと記述可能が、手続き型<ref>[[MISRA C]]のように副作用を極力用いないプログラミングを推奨しているコーディング標準記述でき。</ref>
逆に手続き型言語を使って関数型プログラミングを行うことも可能である。
 
== 概要 ==
<!--関数型プログラミングではプログラムの構成にC言語のように関数を多用する<ref>The C language is purely functional http://conal.net/blog/posts/the-c-language-is-purely-functional</ref>。[[Wikipedia:検証可能性#通常は信頼できないとされる情報源]]-->関数型プログラミングでは関数を[[第一級オブジェクト]]として扱う。理論的な計算モデルとして第一級オブジェクトとしての関数を扱える[[ラムダ計算]]や[[項書き換え]]を採用している。
 
コンピュータプログラムは通例入力を受け取って何らかの処理を行ない、出力を返すことを目的として書かれる。数学の関数<math>y = f(x)</math>において、<math>x</math>を入力、<math>y</math>を出力と考えると、コンピュータプログラムはある種の関数であると考えることができる。ここで、入力や出力は記憶装置中のファイルのようなものばかりではなく、マウキーボードや[[ポインティングデバイの動きの]]によってユーザーから与えられる情報といった入力や、画面への表示といった出力形態も考えられる。関数型プログラミングにおいては実際にそれらを扱う関数としてモデル化する。
関数への引数がプログラムへの入力で、関数を引数に作用させて評価して得る値がプログラムからの出力である。
入力と出力以外の作用を副作用という。C言語のように関数プログラミングしやすい言語であっても、副作用が生じることを許容している。
しかし、MISRA Cコーディング標準のようにC言語の副作用を極力用いないプログラミングを推奨しているものもある。
 
コンピュータプログラムはある種の関数であると考えることができる。ここで、入力や出力は記憶装置中のファイルのようなものばかりではなく、マウスの動きの情報といった入力や、画面への表示といった出力も考えられ、関数型プログラミングにおいては実際にそれらを扱う関数としてモデル化する。
 
純粋関数型言語では、[[参照透過性]]が常に保たれるという意味において、全ての[[式 (プログラミング)|式]]や関数の評価時に[[副作用 (プログラム)|副作用]]を生まない。純粋関数型言語である{{lang|en|[[Haskell]]}}や{{lang|en|[[Clean]]}}は非正格な評価を基本としており、引数はデフォルトで[[遅延評価]]される。一方、{{lang|en|[[Idris]]}}は純粋だが正格評価を採用している。入出力などを[[参照透過性]]を保ったまま実現するために、たとえば {{lang|en|Haskell}} では[[モナド (プログラミング)|モナド]]、{{lang|en|Clean}} では{{仮リンク|一意型|en|Uniqueness type}}という特殊な型を通して一貫性のある表現を提供する。
42 ⟶ 36行目:
非純粋関数型言語では、参照透過性を壊す、副作用があるような式や関数も存在する。{{lang|en|LISP}}などでデータ構造の破壊的変更などの副作用を多用したプログラミングを行うと、それはもはや手続き型プログラミングである。多くの場合、非純粋関数型言語の[[評価戦略]]は正格評価(先行評価)であるが、遅延評価する部分を明示することで、無限リストなどを扱えるものもある。
 
{{lang|en|[[JavaScript]]}}や{{lang|en|[[Java]]}}など{{いつ範囲|date=2018年10月|近年}}の[[高水準言語]]には、関数型言語の機能や特徴を取り入れているものがあるが、変数の値やオブジェクトの状態を書き換えるプログラミングスタイルを通常とするため、関数型言語とは分類されない。一方{{lang|en|[[LISP]]}}は、その多くが副作用のある式や関数が多数あり、手続き型スタイルでのプログラミングがされることも多いが、理論的なモデル(「[[純LISP|純{{lang|en|LISP}}]]」)の存在や副作用を使わないプログラミングが基本であること、ないし主には歴史的理由から、関数型言語だとされることが多い。なお、{{lang|fr|Pascal}}では「手続き」と呼ばれるような値を返さない[[サブルーチン]]を、{{lang|en|C}}言語では<!--<code lang="C">void</code>型の値を返す関数と捉える--><!--void型の値というものは存在せず、存在しないものについて、それを返す関数と「捉える」ことは常人には困難-->「関数」と呼んでいるが、これは単にルーチンについて、細分類して別の呼称を付けているか、細分類せず総称しているか、という分類と呼称の違いに過ぎず「{{lang|fr|Pascal}}は手続き型言語で、C言語は関数型言語」<ref>[[共立出版]]『{{lang|en|ANSI C/C++}}辞典』ISBN 4-320-02797-3 など</ref>という一部の書籍に見られる記述は明確に誤りである。また、{{lang|en|OCaml}}や{{lang|en|Haskell}}などでは、「自明な値(例えば<code>()</code>)を返す」と、値を返さない(<code lang="Haskell">Void</code>など)は違うものであり、後者は停止しないか例外を出す(そのため結果がない)ようなプログラムを表す。
 
なお、「関数型言語である」と「関数型プログラミングをする」は同値ではなく、関数型には分類されない言語で関数型プログラミングをすることや、関数型プログラミングを基本とする言語の上で他のパラダイムを実現する例もある<ref name="Novatchev">{{cite web | url = http://arxiv.org/abs/cs/0509027 | author = Oleg Kiselyov, Ralf Lämmel | title = Haskell's overlooked object system | accessdate = Sep 10, 2005}}</ref>。<!--<ref>「関数型言語」に関するFAQ形式の一般的説明 https://qiita.com/esumii/items/ec589d138e72e22ea97e</ref>[[Wikipedia:検証可能性#通常は信頼できないとされる情報源]]-->
 
[[データフロープログラミング]]言語も関数型言語と共通した特徴を部分的に持つ。
100 ⟶ 94行目:
|-
|{{lang|en|[[Unlambda]]}}||非純粋||型なし
|-
|{{lang|en|[[C]]}}||非純粋||強化中、静的
|-
|{{lang|en|[[C++]]}}||非純粋||強化中、静的
|}
 
従来の手続き型と分類されるプログラミング言語においても、関数型プログラミングを行ないやすくなる機能を備えているものもある。[[C言語]]および[[C++]]は[[関数へのポインタ]]をサポートし、関数をオブジェクトのように扱うことができるが、[[第一級関数]]をサポートしているとみなされてはいない。なお、[[C++]]は[[C++11]]規格においてラムダ式(無名関数)をサポートすることで、[[ラムダ計算]]が可能となった。
 
=== その他の関数的性質を持つ言語 ===