7

pure function次のような非常に単純な例の概念には問題ありません...

function addTwo(val){
   return val + 2;
}

同じ引数を指定すると、同じ結果が得られ、参照透過性と優れた決定論的コードにつながります。

しかし、その後、私はこれらのような例に出くわしました(フリスビー教授のほとんど適切なガイドから取得しましたが、他のFP JS本で同様の例を見つけました)

//pure
var signUp = function(Db, Email, attrs) {
  return function() {
    var user = saveUser(Db, attrs);
    welcomeUser(Email, user);
  };
};

var saveUser = function(Db, attrs) {
  ...
};

var welcomeUser = function(Email, user) {
  ...
};

また、外部依存関係 (つまり、不純) と見なされない理由がわかりませんsaveUserorへの呼び出しwelcomeUser

関数/IO の観点からは、signUp常に「同じ」(同等の) 有線関数を返すことはわかっていますが、私には奇妙に感じます。

理由さえ理解するのは難しい

function multiplyBy(times){
  return value => value * times;
}
const fiveTimes = multiplyBy(5);
fiveTimes(10);

と考えられpureます。返された関数 POV から、アクセスtimesはスコープ チェーンのルックアップであり、すぐ外側のスコープから、またはそれを超えて (グローバル スコープのように) 来る可能性があります。

これに光を当てたい人はいますか?

4

2 に答える 2

17

JavaScript における関数の純粋性についての私の説明は、バイナリの「純粋」または「不純」などというものは存在せず、関数が予測どおりに動作するという信頼のスペクトルがあるということです。たとえば、副作用ゲッターを含むオブジェクトを渡すなど、純粋に見える関数をそうでないようにするためにプレイできるあらゆる種類のトリックがあります。

したがって、純度とは信頼度に関するものであることがわかったら、次のように尋ねることができます。その関数が別の関数を参照している場合、その関数が純粋であるという確信はありますか? さらに、その他の関数を参照している識別子が、認識していない他の関数を指すように再割り当てされない/できないことをどの程度確信していますか?

私は自分のプログラムを個人的にコーディングしているので、特にその関数が関数式ではなく宣言されている場合は、関数を指す識別子を再定義することはほとんどありません。そのようにして、私は非常に自信を持っています (たとえば、99.99%) iffoo(..)が呼び出され、それが確実に純粋であるとbar(..)確信しています。 .bar(..)foo(..)bar(..)

で関数識別子を定義するところまで行く人もいますconst fn = function ..。それはあまり役に立たないと思います...おそらく、私の信頼レベルが99.99%から99.999%になるでしょう. それは、その使用を正当化するのに十分なほど針を動かしません、IMO。

さらに、あなたの質問のクロージャー部分について:内部関数が純粋な関数にまだ含まれている外部変数を閉じ、何もその変数を再割り当てしない場合、それは事実上定数であるため、私の自信のレベルは非常に高いです予測可能性。

しかし、繰り返しますが、JS における関数の純粋性は信頼レベルに関するものであり、絶対的な二者択一のイエスかノーではないということです。

于 2016-10-03T15:18:20.080 に答える
6

純粋関数の定義は次のとおりです。

同じ引数値が指定された場合に常に同じ結果値を評価し、変更可能なオブジェクトの変更や I/O デバイスへの出力など、意味的に観察可能な副作用や出力を引き起こさない関数。

「依存関係を持つ」ことは、純粋な関数を定義する上でまったく役割を果たしません。重要なのは、関数に副作用があるかどうか、およびその結果が外部状態に依存するかどうかだけです。関数がまったく同じように動作し、同じ入力に対して常に同じ結果を生成する場合、その関数は純粋です。関数に何らかの副作用 (グローバル状態を変更する) がある場合、または外部状態に応じて異なる動作をする場合、その関数は不純です。関数は、その操作の一部として別の関数に依存する (read: call ) 場合があります。他の関数も純粋である限り、純粋性が損なわれることはありません。

表示するsignUp例は純粋です。これは、入力に対してのみ機能し、同じ入力で呼び出されたときに常にまったく同じ出力を返すためです。関数自体は何も「実行」しないことに注意してください。データベースを呼び出したり、副作用を引き起こしたりすることはありません。関数を返すだけです。ただし、入力が同じであれば、この返される関数は常に同じです。その返された関数は事実上不純です。しかし、それを生成した関数はそうではありません。

于 2016-10-03T15:04:36.680 に答える