web-dev-qa-db-ja.com

不純な関数が構成できないと言われるのはなぜですか?

私は純粋な関数が何であるかを理解し、誰かが純粋な関数は合成可能であると言ったとき-私はそれはある関数の出力が別の関数への入力として渡されることができることを意味しますが、同じことが純粋でない関数でも同様ですよね?以下の2つの関数を実行します。

int sum(int a, int b) {
    print("sum");
    return a + b;
}

void save(int result) {
    DB.save(result);
}

void PersistSum(int a, int b) {
    save(sum(a,b));
}

saveおよびsum関数には副作用がありますが、PersistSumのように構成できます。

ここでは、構成可能性の中心的な意味が欠けていると思います。誰かが構成可能性が何を意味するのか、そして副作用を持つ関数が例で構成できない理由の正確な意味を提供できますか?

7
rahulaga_dev

関数構成 は確かに、ある関数の出力に別の関数を適用する新しい関数を作成しています。 より一般的には 、合成により、他のいくつかの関数を組み合わせて新しい関数を作成できます。

純粋な関数 は、同じ入力に対して常に同じ出力を提供し、副作用のない関数です。つまり、結果だけが重要であるため、必要な頻度を呼び出すことができる、驚きのない関数です。

純粋な関数を作成できます。定義により、純粋な関数を取得します。

不純な関数を作成することもできます。リスクが高いというだけです。

h(x) = g(f(x))の例を見てみましょう:

  • Fとgに2つの完全に独立した副作用sfとsgがある場合、これらの副作用は次の順序で発生します:最初にsf、次にsg。
  • 副作用が独立していない場合、合成は予期しない影響を与える可能性があります。

ここで、いくつかの変数と3つ以上の関数を使用して、より複雑な構成があるとします。h(x、y)= g(f1(x、y)、f2(x、y))。すでに述べたように、これらの関数がすべて純粋であれば、結果は驚くことなく純粋になります。これらの関数が不純である場合、多くの未解決の問題が発生します。

  • これらの各関数に独立した副作用sg、sf1、sf2があるとします。ここでは、これらの副作用の順序を予測できなくなりました。sf1、sf2、sgの可能性があります。 sf2 sf1 sgの場合もあれば、sf1とsf2がまったく同じ時間でsgの場合もあります。
  • これらの副作用が独立していないと仮定します。たとえば、sf1がグローバル変数に1を追加し、sf2が同じグローバル変数に2を乗算する場合、グローバル変数に対するhの影響は予測できません。
13
Christophe

純粋な関数を含む式は書き換えることができ、副作用は別の方法で発生します。

f x = { print(x), x }
^ (xor) is commutative an associative, x ^ 0 == x, x ^ x == 0

これは、用語を再利用することで、重複を除外するために使用できます。

f 3 ^ f 5 ^ f 7 ^ f 5 ^ f 3 ==
(f 3 ^ f 3) ^ (f 5 ^ f 5) ^ f 7  ==
0 ^ 0 ^ f 7 ==
f 7 ==                     -- Just one print(7)
7

したがって、副作用が無視される場合、副作用は異なる順序で発生するか、まったく発生しない可能性があります。

私のポイント:関数構成は、式ツリーの操作にも関係しています。

(また、同じ引数を持つ2つの呼び出しが同じ結果をもたらす保証はないことに注意してください。しかし、意図していないその側面。)

1
Joop Eggen