以下のようヤニスは指摘し、せずに以前いた言語で、高次機能の採用に影響を与えたいくつかの要因があります。彼が軽く触れた重要な項目の1つは、マルチコアプロセッサの急増であり、それにより、より並列および同時処理が望まれています。
関数型プログラミングのmap / filter / reduceスタイルは、並列化に非常に適しているため、プログラマは明示的なスレッドコードを記述することなく、複数のコアを簡単に利用できます。
Giorgioが指摘しているように、関数型プログラミングには単なる高階関数以上のものがあります。関数、さらにmap / filter / reduceプログラミングパターン、および不変性は、関数型プログラミングの中核です。これらを組み合わせることで、並列および並行プログラミングの強力なツールが作成されます。ありがたいことに、多くの言語はすでに不変性の概念をサポートしており、プログラマーはそれを不変として扱い、ライブラリーとコンパイラーが非同期または並列操作を作成および管理できるようにします。
高次関数を言語に追加することは、並行プログラミングを簡素化するための重要なステップです。
更新
Lokiが指摘した懸念に対処するために、さらに詳細な例をいくつか追加します。
ウィジェットのコレクションを走査して、ウィジェットの価格の新しいリストを作成する次のC#コードを検討してください。
List<float> widgetPrices;
float salesTax = RetrieveLocalSalesTax();
foreach( Widget w in widgets ) {
widgetPrices.Add( CalculateWidgetPrice( w, salesTax ) );
}
ウィジェットの大規模なコレクション、または計算集約的なCalculateWidgetPrice(Widget)メソッドの場合、このループは利用可能なコアをうまく利用しません。異なるコアで価格計算を行うには、プログラマーがスレッドを明示的に作成および管理し、回避策を渡し、結果を一緒に収集する必要があります。
高次関数がC#に追加された後の解決策を検討してください。
var widgetPrices = widgets.Select( w=> CalculateWidgetPrice( w, salesTax ) );
foreachループはSelectメソッドに移動され、実装の詳細が非表示になりました。プログラマーに残るのは、Selectに各要素に適用する機能を選択することだけです。これにより、Select実装は、Parellelで計算を実行し、プログラマーの関与なしにすべての同期およびスレッド管理の問題を処理できます。
しかし、もちろん、Selectは並行して動作しません。そこで不変性が生じます。Selectの実装は、提供された関数(上記のCalculateWidgets)に副作用がないことを知りません。この関数は、Selectのビューとその同期の外側でプログラムの状態を変更し、すべてを壊す可能性があります。たとえば、この場合、salesTaxの値は誤って変更される可能性があります。純粋な関数型言語は不変性を提供するため、Select(マップ)関数は状態が変化していないことを確実に知ることができます。
C#は、Linqの代替としてPLINQを提供することでこれに対処します。次のようになります。
var widgetPrices = widgets.AsParallel().Select(w => CalculateWidgetPrice( w, salesTax) );
これらのコアを明示的に管理することなく、システムのすべてのコアを最大限に活用します。