関数型プログラミングの違いは何ですか?
関数型プログラミングは原則として宣言型です。計算方法ではなく、結果が何であるかを言います。
スニペットの実際に機能する実装を見てみましょう。Haskellでは次のようになります。
predsum pred numbers = sum (filter pred numbers)
それは明らかである何結果は?かなりそうです、それは述語を満たす数の合計です。どのように計算されますか?私は気にしません、コンパイラに尋ねます。
あなたは、おそらく使用していることを言うことができるsum
とfilter
トリックであり、それはカウントされません。これらのヘルパーなしで実装してみましょう(最善の方法は最初に実装することです)。
使用しない「Functional Programming 101」ソリューションsum
は、再帰によるものです。
sum pred list =
case list of
[] -> 0
h:t -> if pred h then h + sum pred t
else sum pred t
単一の関数呼び出しに関して、結果がどうなるかはまだはっきりしています。それはどちらかである0
、またはrecursive call + h or 0
に応じて、pred h
。最終結果がすぐに明らかではない場合でも、かなり単純です(ただし、少し練習するだけで、for
ループのように読み取れます)。
それをあなたのバージョンと比較してください:
public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
int result = 0;
foreach(var item in numbers)
if (predicate(item)) result += item;
return result;
}
結果はどうですか?ああ、わかりました:単一のreturn
ステートメント、ここに驚きはありません:return result
。
しかし、何result
ですか?int result = 0
?正しくないようです。あなたはそれで後で何かをし0
ます。OK、あなたはそれにitem
sを追加します。等々。
もちろん、ほとんどのプログラマーにとって、これはこのような単純な関数で何が起こるかは非常に明白ですが、追加のreturn
ステートメントなどを追加すると、突然追跡が難しくなります。すべてのコードはどのように、そして読者が理解するために残されているものについてです- これは明らかに非常に必須のスタイルです。
それで、変数とループは間違っていますか?
番号。
彼らによってはるかに簡単に説明できるものがたくさんあり、可変状態を高速にするために必要な多くのアルゴリズムがあります。しかし、変数は本質的に必須であり、whatではなくhowを説明し、数行後または数回のループ反復後にそれらの値が何であるかをほとんど予測しません。ループは一般的に意味を成すために状態を必要とするので、本質的に必須です。
変数とループは、単に関数型プログラミングではありません。
概要
現代の関数型プログラミングは、パラダイムというよりは、少しスタイルがあり、便利な考え方です。純粋な関数を強く好むのはこの考え方ですが、実際にはほんの一部にすぎません。
ほとんどの一般的な言語では、いくつかの関数構成を使用できます。たとえばPythonでは、次のいずれかを選択できます。
result = 0
for num in numbers:
if pred(result):
result += num
return result
または
return sum(filter(pred, numbers))
または
return sum(n for n in numbers if pred(n))
これらの関数式は、その種の問題にうまく適合し、コードを短くします(短くするのが良いです)。命令型コードを不用意にそれらに置き換えるべきではありませんが、それらが適合する場合、ほとんどの場合、それらはより良い選択です。
item
ループ内で変数が変更された場合、副作用はありません -副作用があります。