コアポイント
プログラマーとして、エレガントで保守可能で、スケーラブルで予測可能なコードを書きたいと思うかもしれません。機能プログラミング(FP)の原則は、これらの目標を達成するのに大いに役立ちます。
機能プログラミングは、不変性、一流の機能、引用の透明性、純粋な機能を強調するパラダイムまたはスタイルです。これらの言葉の意味を理解していない場合は、心配しないでください!この記事では、これらすべての用語を分類します。
機能プログラミングは、関数の抽象化と一般化を中心に展開する数学システムであるλ計算に由来します。したがって、多くの機能的なプログラミング言語は非常に数学的であるように見えます。しかし、良いニュースは、機能的なプログラミング言語を使用して、機能的なプログラミング原則をコードに適用する必要はありません。この投稿では、JavaScriptを使用します。JavaScriptには、そのパラダイムに限定されることなく、機能的なプログラミングに適した多くの機能があります。
機能プログラミングのコア原則
機能プログラミングとは何かについて説明したので、FPの背後にある核となる原則について説明しましょう。
機能をマシンと考えるのが好きです - 入力またはパラメーターを受け入れてから、何か、つまり戻り値を出力します。純粋な機能には、関数出力とは無関係の「副作用」や操作はありません。いくつかの潜在的な副作用には、値の印刷またはconsole.log
で記録するか、関数の外側の変数を操作することが含まれます。
これは、非純粋な関数の例です:
let number = 2; function squareNumber() { number = number * number; // 非纯操作:操作函数外部的变量 console.log(number); // 非纯操作:控制台记录值 return number; } squareNumber();
次の関数は純粋な関数です。入力を受け入れ、出力を生成します。
let number = 2; function squareNumber() { number = number * number; // 非纯操作:操作函数外部的变量 console.log(number); // 非纯操作:控制台记录值 return number; } squareNumber();
純粋な関数は、関数の外側の状態とは独立して実行されるため、グローバルな状態や自分の外の変数に依存しないでください。最初の例では、関数の外側で作成されたnumber
変数を使用し、関数内で設定します。これはこの原則に違反します。グローバル変数の変更に大きく依存している場合、コードは予測不可能で追跡が困難になります。エラーが発生した場所と値が変化する理由を見つけることは、より困難です。代わりに、入力、出力、および機能ローカル変数のみを使用すると、デバッグが簡単になります。
参照透明度に従う必要があります。つまり、入力が与えられた場合、それらの出力は常に同じです。上記の例では、2を関数に渡すと、常に4が返されます。これは、API呼び出しや乱数の生成には当てはまりません。これらは2つの例です。同じ入力が与えられた場合、出力が返される場合と返されない場合があります。
// 纯函数 function squareNumber(number) { return number * number; } squareNumber(2);
invariability、つまり、直接変更されているものはありません。不変性は予測可能性をもたらします - データの価値がわかっているので、変更されません。コードをシンプルでテスト可能にし、分散型およびマルチスレッドシステムで実行します。
データ構造を使用すると、不変性が役割を果たすことがよくあります。 JavaScriptの多くの配列メソッドは、アレイを直接変更します。たとえば、アレイの端から直接アイテムを削除しますが、.pop()
を使用すると、配列の一部を取得できます。代わりに、機能パラダイムでは、配列をコピーして、プロセスで削除する要素を削除します。 .splice()
// 不具有引用透明性 Math.random(); // 0.1406399143589343 Math.random(); // 0.26768924082159495
// 我们直接修改 myArr const myArr = [1, 2, 3]; myArr.pop(); // [1, 2]
// 我们复制数组而不包含最后一个元素,并将其存储到变量中 let myArr = [1, 2, 3]; let myNewArr = myArr.slice(0, 2); // [1, 2] console.log(myArr);
、map
、reduce
など、配列との対話にそれらを使用できます。 filter
は、私たちが提供する条件を満たす値のみを含む古い配列から新しい配列を返すために使用されます。 filter
let myFunctionArr = [() => 1 + 2, () => console.log("hi"), x => 3 * x]; myFunctionArr[2](2); // 6 const myFunction = anotherFunction => anotherFunction(20); const secondFunction = x => x * 10; myFunction(secondFunction); // 200
は、配列内のアイテムを反復し、提供されたロジックに従って各アイテムを変更するために使用されます。次の例では、値を2に乗算する関数を渡すことにより、各アイテムを配列内に2倍にします。 map
map
const myArr = [1, 2, 3, 4, 5]; const evens = myArr.filter(x => x % 2 === 0); // [2, 4]
reduce
const myArr = [1, 2, 3, 4, 5]; const doubled = myArr.map(i => i * 2); // [2, 4, 6, 8, 10]
filter
2番目のタイプの高次関数(他の関数を返す関数)も比較的頻繁なパターンです。たとえば、
let number = 2; function squareNumber() { number = number * number; // 非纯操作:操作函数外部的变量 console.log(number); // 非纯操作:控制台记录值 return number; } squareNumber();
カレーにも興味があるかもしれないので、読むことができます!
関数の組み合わせは、複数の単純な関数を組み合わせて、より複雑な関数を作成することです。したがって、平均関数と配列の値を合計する合計関数を組み合わせるaverageArray
関数を持つことができます。個々の機能は小さく、他の目的のために繰り返され、より完全な作業を行うために結合することができます。
// 纯函数 function squareNumber(number) { return number * number; } squareNumber(2);
利点
関数プログラミングは、モジュラーコードを生成します。繰り返し使用できる関数が少ないです。各関数の特定の機能を理解することは、特に関数出力が予測可能である場合、エラーを特定してテストを書き込むのが簡単であることを意味します。
また、複数のコアを使用しようとすると、これらのコアに関数呼び出しを配布できるため、計算効率を改善できます。
機能プログラミングの使用方法は?
これらすべてのアイデアを統合するために、機能的なプログラミングに完全に目を向ける必要はありません。オブジェクト指向のプログラミングでは、多くのアイデアをよく使用することもできます。これは、ライバルと見なされることがよくあります。たとえば、
は、不変の状態などの多くの機能原理を組み込んでいますが、主に長年にわたってクラスの構文を使用しています。また、ほぼすべてのプログラミング言語で実装することもできます。実際に望まない限り、ClojureやHaskellを書く必要はありません。あなたが純粋主義者ではない場合でも、機能的なプログラミングの原則は、コードで肯定的な結果を生み出すことができます。
機能的なプログラミングに関するよくある質問機能プログラミングの重要な原則は何ですか?
機能プログラミングと手続き上のプログラミングの違いは何ですか?
機能プログラミングの利点は何ですか?
機能プログラミングには多くの利点がありますが、いくつかの課題もあります。特に手続き型またはオブジェクト指向のプログラミングに慣れている人々にとって、学ぶことは困難です。機能スタイルで特定のアルゴリズムを実装することもより困難です。さらに、機能的なプログラミングは、既存のオブジェクトを変更するのではなく新しいオブジェクトを作成することが多いため、効率の低いコードにつながる場合があります。
多くのプログラミング言語は、機能的なプログラミングをある程度サポートしています。 HaskellやErlangなどの一部の言語は純粋に機能的であり、JavaScriptやPythonなどの言語は、機能的なプログラミングやその他のパラダイムをサポートするマルチパラダイム言語です。 JavaやCなどの機能的プログラミングと伝統的に関係のない言語でさえ、近年、機能プログラミングをサポートする機能を追加しています。
機能プログラミングでは、副作用を可能な限り避けてください。これは、状態を変更したり、I/O操作を実行したりしない純粋な関数を使用して行われます。副作用が必要な場合、それらは分離され、制御されます。たとえば、Haskellでは、副作用がモナドで扱われ、副作用をカプセル化し、制御された方法でそれらをリンクする方法を提供します。
高次関数は、パラメーターとして1つ以上の関数を取得したり、結果として関数を返したり、同時に両方の操作を実行する関数です。高度な注文機能は、機能をデータとして使用できるため、機能プログラミングの重要な機能です。これにより、よりクリーンでより表現力のあるコードにつながる可能性があります。
再帰は、関数が独自の定義でそれ自体を呼び出すテクニックです。機能プログラミングでは、ループには機能的なプログラミングで回避される可変状態が含まれるため、ループの代替として再帰が使用されることがよくあります。再帰を使用して、要因の計算から木の通過まで、さまざまな問題を解決することができます。
Curryingは、複数のパラメーターを持つ関数が一連の関数に変換される機能プログラミングの手法であり、各関数には1つのパラメーターのみがあります。これにより、関数の一部が適用されます。ここで、1つの関数がそのパラメーターの一部に適用され、残りのパラメーターを取る新しい関数を返します。
機能的反応性プログラミング(FRP)は、機能的なプログラミングと反応性プログラミングを組み合わせたプログラミングパラダイムです。 FRPでは、プログラム状態は時間とともに変化する一連の不変の値としてモデル化されており、関数はこれらの値を変換および結合するために使用されます。これにより、非同期およびイベント駆動型のプログラムについて推論することが容易になります。これは、変動可能な状態や副作用を回避するためです。
以上が機能プログラミングとは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。