私は関数型プログラミングの多くの機能を列挙することができますが、友人が私に尋ねたとき、関数型プログラミングを定義してくれませんか? 私はできませんでした。
8 に答える
純粋な関数型プログラミングの決定的なポイントは、すべての計算が副作用のない関数で行われることです。つまり、関数は入力と戻り値を受け取りますが、非表示の状態を変更しません。このパラダイムでは、関数は数学的な従兄弟をより厳密にモデル化します。
これは、ライトワンス スタックを備えた言語である Erlang を使い始めたときにはっきりとわかりました。ただし、プログラミングパラダイムとプログラミング言語には違いがあることを明確にする必要があります。一般に関数型言語と呼ばれる言語は、関数型パラダイムを促進または強制する多くの機能を提供します (たとえば、Erlang の write-once スタック、高階関数、クロージャなど)。ただし、関数型プログラミングのパラダイムは多くの言語に適用できます (さまざまな程度の苦痛を伴います)。
これまでの定義の多くは純粋さを強調してきましたが、機能的であると見なされ、まったく純粋ではない言語がたくさんあります(ML、Schemeなど)。言語を「機能的」にする重要な特性は次のとおりです。
- 高階関数。関数は、整数やブール値と同じように組み込まれたデータ型です。匿名関数は簡単に作成でき、慣用的です(ラムダなど)。
- すべてが表現です。命令型言語では、状態を変化させて制御フローに影響を与えるステートメントと、値を生成する式を区別します。関数型言語(不純な関数型言語でさえ)では、式の評価が実行の基本単位です。
これらの2つのプロパティが与えられると、当然、機能的であると考える動作が得られます(たとえば、フォールドとマップの観点から計算を表現する)。可変状態を排除することは、物事をさらに機能的にする方法です。
ウィキペディアから:
コンピューター サイエンスでは、関数型プログラミングは、計算を数学関数の評価として扱い、状態データや可変データを回避するプログラミング パラダイムです。状態の変化を重視する命令型プログラミング スタイルとは対照的に、関数の適用を重視します。
関数型アプローチを使用すると、次の利点が得られます。
- 並行プログラミングは、関数型言語の方がはるかに簡単です。
- FP の関数は副作用を引き起こすことはありません。これにより、単体テストがはるかに簡単になります。
- 本番環境でのホット コード デプロイは、はるかに簡単です。
- 関数型言語は、数学的に推論できます。
- 遅延評価は、パフォーマンスの最適化の可能性を提供します。
- 表現力の向上 - クロージャー、パターン マッチング、高度な型システムなどにより、プログラマーはより簡単に「意味を言う」ことができます。
- 簡潔さ - 一部のクラスのプログラムでは、関数ソリューションの方がはるかに簡潔です。
ここに詳細が記載されたすばらしい記事があります。
機能を列挙できることは、用語自体を定義しようとするよりも便利です。人々は「関数型プログラミング」という用語をさまざまな文脈で使用し、連続体全体にさまざまな意味の色合いがありますが、個々の機能には個別に明確な定義があります。より普遍的に合意されています。
以下、思いつく特徴です。ほとんどの人は、「関数型プログラミング」という用語を、これらの機能のサブセットを指すために使用します (最も一般的/重要なものは「純度」と「高階関数」です)。
FP の特徴:
- 純度(別名不変性、回避する副作用、参照透過性)
- 高階関数(例: 関数をパラメーターとして渡し、結果として返す、匿名関数をその場でラムダ式として定義する)
- 怠惰(別名非厳密な評価、純度と組み合わせると最も有用/使用可能)
- 代数データ型とパターン マッチング
- 閉鎖
- カリー化・部分適用
- パラメトリック ポリモーフィズム(別名ジェネリック)
- 再帰(純度の結果としてより顕著)
- ステートメントではなく式を使用したプログラミング (これも純粋性から)
- ...
上記のリストからより多くの機能を使用すればするほど、誰かがあなたが行っていることを「関数型プログラミング」とラベル付けする可能性が高くなります (そして最初の 2 つの機能 (純粋関数と高階関数) は、おそらく最もボーナスポイントに値するものです)あなたの「FPスコア」)。
関数型プログラミングは、ドメインだけでなくプログラムの制御構造も抽象化する傾向があることを付け加える必要があります。たとえば、いくつかのリストで「forループ」を実行するのではなく、生成する関数でそれを「マップ」します。出力。
関数型プログラミングは、上記の定義と同様に心の状態だと思います。
2 つの別個の定義があります。
古い定義 (第一級関数) は Chris Conway によって与えられました。
新しい定義 (突然変異のような副作用を避ける) は、John Stauffer によって与えられました。これは、より一般的には純粋関数型プログラミングとして知られています。
これは多くの混乱の元です...
ジョン・スタウファーがほとんど定義していると思います。また、関数を渡すことができる必要があることも付け加えておきます。つまり、関数を簡単に渡すことができます (ただし、ブロックを渡すだけで十分です)。
たとえば、非常に一般的な関数呼び出しは map です。基本的に同等です
list is some list of items
OutList is some empty list
foreach item in list
OutList.append(function(item))
return OutList
コードはマップ(関数、リスト)として表現されます。革新的な概念は、機能は機能であるということです。Javascript は、高次関数を備えた言語の好例です。基本的に、関数は変数のように扱われ、関数に渡されるか、関数から返されます。C++ と C には、同様に使用できる関数ポインターがあります。.NET デリゲートも同様に使用できます。
そうすれば、あらゆる種類のクールな抽象化を考えることができます...
AddItemsInList、MultiplyItemsInList などの関数はありますか?
各関数は (List) を取り、単一の結果を返します
作成することもできます (注: 多くの言語では関数として渡すことができませんが+
、概念を表現する最も明確な方法のようです)。
AggregateItemsInList(List, combinefunction, StepFunction)
インクリメント関数はインデックスで機能します...次のようなリスト操作を使用してリストで機能させ、存在する場合は次のincTwo nextで機能させる方がよいでしょう....
function incNormal(x) {
return x + 1
}
function incTwo(x) {
return x + 2
}
AggregateItemsInList(List, +, incNormal)
他のすべてのアイテムをやりたいですか?
AggegateItemsInList(List, +, incTwo)
増やしたいですか?
AggregateItemsInList(List, *, incNormal)
試験のスコアを一緒に追加したいですか?
function AddScores (studenta, studentb) {
return studenta.score + studentb.score
}
AggregateItemsInList(ListOfStudents, AddScores, incOne)
高階関数は非常に強力な抽象化です。数値、文字列、学生などのカスタム メソッドを作成する代わりに、任意のリストをループ処理する 1 つの集計メソッドがあり、データ型ごとに加算演算を作成するだけです。
これは、ビットマップの代わりにベクトルを使用して絵を描くようなものです。各ステップで絵がどのように見えるかではなく、絵を変更する方法を画家に伝えます。
状態の変更とは対照的に、関数の適用です。