関数型プログラミングについて詳しく解説

オブジェクト言語
C++ – C# – D
デルフィ – エッフェル – グルーヴィー
Java – Python – Ruby
シミュレーション – Smalltalk
Visual Basic – Lisaac – WinDev
命令型言語
APL – ASP –アセンブラ
BASIC – C – COBOL
フォース – Fortran – リンボ
ロゴ – パスカル – Perl – PHP
関数型言語
Haskell – ML/OCaml
Lisp/Common Lisp
スキーム – XSLT
宣言型言語
クリップ –プロローグ
競合言語
Ada 95 – アーラン
こちらも参照
デザイン –コーディング
テスト – 最適化

関数型言語は、その構文と特性が関数型プログラミングを促進する プログラミング言語です。最古の関数型言語は、1958 年にマッカーシーによって作成された Lisp です。 Lisp は、Scheme (1975)、 Common Lisp (1984) などのより最近の亜種を生み出しました。その他の最近の関数型言語には、ML (1973)、Haskell (1987)、Erlang、Clean、Oz または CDuce (2003) などがあります。非 ML 言語のカテゴリーでは、XSLT と Anubis を忘れてはなりません。

ステートマシンと副作用

関数型プログラミングについて詳しく解説

命令型プログラミング

命令型プログラミングでは、中央メモリと、連続した割り当てによって状態を変更する命令を備えたステート マシンのモデル (有限オートマトンチューリング マシン、フォン ノイマンアーキテクチャを参照) に取り組みます。メモリの連続的な状態を表すステート マシンによってプログラムを表すことができます。このため、プログラマは、プログラムが変更しているメモリ状態の正確なモデルを常に知っている必要があります。

このタスクの難易度を下げるために、管理する変数のを減らすことを目的とした多くの手法が使用されています。これらの手法の中で、いわゆる自動変数を挙げることができます。その範囲は、変数が定義されたプロシージャに限定され、プロシージャの終了時にコンパイラによって割り当てが解除されます。データのカプセル化構造化プログラミングの原点、およびオブジェクト指向プログラミング

ただし、プロシージャは、その機能に直接リンクされていない目的で、共有データをプログラマが意図した状態に保つためだけに、特定の変数またはメモリ領域を更新する必要がある場合があります。これらの「リモート」変更は、副作用という一般用語に分類されます。命令型プログラミングにおける副作用は、例外というよりも一般的なもので、プログラムの理解を非常に複雑にし、多くの困難やバグの原因となります。実際、特定の共有データの更新を忘れたり、割り当ての時系列順序が崩れたりすると、ソフトウェアのさまざまな部分が正しくない場合、またはメモリ領域の割り当てが間違ったタイミングで解除された場合、プログラムは予期しない状態になります。

関数型プログラミング

関数型プログラミングは、代入操作を一切禁止することで副作用を根本的に軽減します。

関数パラダイムは、プログラムを記述するためにステート マシンを使用するのではなく、相互にネストできる「ブラック ボックス」と見なされる関数のネストを使用します。各ボックスには複数の入力パラメータがありますが、出力は 1 つだけであり、入力として提示された値のタプルごとに 1 つの可能な値のみを出力できます。したがって、この関数によって副作用が生じることはありません。したがって、プログラムは数学的な意味でのアプリケーションであり、入力値の各セットに対して 1 つの結果のみを返します。この考え方は、命令型プログラミングにおける通常の考え方とは大きく異なり、命令型言語で訓練を受けたプログラマが関数型プログラミングに取り組むことを困難にする主な原因の 1 つです。ただし、命令型言語に慣れたことのない初心者にとっては、通常、特別な困難を引き起こすものではないことに注意してください。副作用のない関数の重要な利点は、関数を個別にテストするのが簡単であることです。さらに、ガベージコレクターによる自動メモリ管理が広く使用されているため、プログラマの作業が簡素化されています。

実際には、効率性の理由と、特定のアルゴリズムがステート マシンで簡単に表現できるという事実から、特定の関数型言語では、特定の変数が割り当て可能 (または通常の名称に従って変更可能) であることを指定できるようにすることで命令型プログラミングを許可しています。 、したがって局所的に副作用が導入される可能性があります。これらの言語は、不純な関数型言語としてグループ化されます。

いわゆる純粋関数型言語では、命令型プログラミングは許可されません。実際、これらには副作用がなく、同時実行によって引き起こされる問題から保護されています。たとえば、Erlang 言語のフレームワーク内で何が行われたかを確認できます。

関数型言語の実装では、一時データを配列に格納する必要性を克服するために、再帰を多用するため、スタックを高度に利用します。つまり、独自の定義に関数の呼び出しを含めるという事実です。 -。再帰は、 tail-recursionと呼ばれる手法を使用してより効率的に行うことができます。これは、中間結果をスタック上のメモリ スロットに蓄積し、それを再帰呼び出しのパラメータとして渡すことで構成されます。これにより、再帰呼び出しが単純なジャンプの連続に置き換えられるため、スタック内に再帰呼び出しが積み重なることがなくなります。コンパイラーによって生成されるコードは、命令型ループによって生成されるコードと似ています。 Scheme、OCaml、Anubis などの一部の言語は、この方法で再帰呼び出しを自動的に最適化します。

関数型プログラミングについて詳しく解説

参照透明性

関数型言語のもう 1 つの特性は、参照の透明性です。この用語は、式を同じ値の式に置き換えてもプログラムの結果が変わらないという単純な原理をカバーしています。この原則は、副作用のあるプロシージャの場合には違反します。そのようなプロシージャは入力引数だけに依存せず、プログラム内の 2 つの指定された時点で必ずしも同じように動作するとは限らないからです。ただし、参照の透明性は、後で説明するように、非常に便利な特性です。

例を挙げてみましょう。 C で、 n がインクリメントされる整数を含むグローバル変数(つまり、プログラム全体から見えるメモリ ボックス) を指定し、 inc(k) がnの値をkだけ増やす関数を指定するとします。

int n = 2;
int inc(int k) { n = n + k; n を返します。 } /* 副作用により増加します*/
f(inc(1) + inc(1));

この例では、 inc(i)関数は 2 回の呼び出しで同じ値を返しません。関数fの引数の 1 つは2 + 1 = 3 の価値があり、もう 1 つは3 + 1 = 4 の価値があります。したがって、 inc(i)の値は呼び出しごとに異なるため、 inc(i) + inc(i)2 * inc(i)に置き換えることは不可能であることがわかります。この動作は数学関数の動作とは根本的に異なります。大規模なプログラムの場合、これは、ある関数を別の関数に置き換えるには、プログラム内の他の場所に変更が必要になる可能性があり、そのような置き換えによって全体の動作が変更されていないことを確認できないため、システム全体の再テストが必要になる場合があることを意味します。システムが複雑になるにつれて、変更のコストも増加します。逆に、参照透過性プロパティにより、関数を別の同等の関数に置き換えても、プログラムの全体的な動作が変更される危険がなくなります。言い換えれば、それらは数学的に等しいということです。この特性により、ソフトウェアのメンテナンスが容易になります。また、動作証明を自動的に適用することも可能です。最後に、実行順序の重要性が大幅に軽減されるというもう 1 つの利点もあり、これは関数の呼び出し順序によって保証されます。その結果、関数型プログラムの並列化が自動的に実行できることになります。

より優れた表現力

関数型言語は、拡張可能なリストのような高レベルのデータ型と構造を採用します。したがって、一般に、リストの連結やリストへの関数の適用 (リストは再帰的に走査されます) などの操作を 1 行のコードで簡単に実行できます。

関数型言語の強力なメカニズムは、高階関数の使用です。関数が引数 (コールバックとも呼ばれる) として関数を受け取ることができる場合、および/または結果として関数を返すことができる場合、関数は高階であると言われます。関数はファーストクラスのオブジェクトとも言われます。これは、関数が基本型と同じくらい簡単に操作できることを意味します。それらは、数学では関数に対応します。導出演算と積分演算は 2 つの単純な例です。高階関数は、多くの関数型言語、特に Haskell の設計に大きな影響を与えた形式主義であるラムダ計算形式主義に基づいて、1930 年代にAlonzo Churchと Stephen Kleene によって研究されました。ただし、閉デカルト圏理論では、普遍的な問題の概念を使用して、より現代的な方法で関数を特徴付けます。

関数型プログラミングについて詳しく解説

関数型パラダイムの人気

経験豊富なプログラマーの多くは、関数型プログラミングには命令型において比類のない利点があると信じています。それにもかかわらず、学術界や愛好家以外ではほとんど使用されていません。産業環境では、Erlang (競技プログラミングのニーズと堅牢性の要件のためにエリクソンによって開発された) 言語、Common Lisp、および Scheme が使用されます。しかし、関数型言語の開発は、商用品質のツールやライブラリの欠如、特に訓練を受けたプログラマーの不足によって制限されています。

最後に、関数型言語は依然として遅いという評判に悩まされていますが、これは今日では完全に不当です: Stalin や Bigloo コンパイラーなどの特定の Scheme コンパイラー、Common Lisp 用のコンパイラー、 Objective Camlなどの ML に沿った言語、または Still Haskell は、平均パフォーマンスが C または C++ コンパイラで生成されるものと同等かそれよりも優れた実行可能ファイルを生成します。

大学や特定の産業部門の外では、XSLT が機能パラダイムを普及させるベクトルとなる可能性があります。 XML 処理に特化しているため、プログラマは命令型言語またはオブジェクト言語を維持しながら、通常の構文では得られない優雅さと明瞭さで別のロジックを発見できます。

  1. برمجة وظيفية – arabe
  2. Programación funcional – asturien
  3. Функцыянальнае праграмаванне – biélorusse
  4. Функционално програмиране – bulgare
  5. ফাংশনভিত্তিক প্রোগ্রামিং – bengali
  6. Programació funcional – catalan

関数型プログラミングについて詳しく解説・関連動画

サイエンス・ハブ

知識の扉を開け、世界を変える。