web-dev-qa-db-ja.com

別の関数から値を取得する関数は純粋と見なされますか?

副作用のない関数を作成するときにデフォルトの変数値を処理する方法を理解しようとしていますが、次のようになっています。

function getDefaultSeparator() {
    return ':';
}

function process(input, separator) {
    var separator = separator || getDefaultSeparator();

    // Use separator in some logic

    return output;
}

デフォルトのセパレーターは他の関数で使用され、1つの場所でのみ定義したいと思います。

これが純粋な関数である場合、代わりにグローバルDEFAULT_SEPARATOR定数を使用することとの違いは何ですか?

9
agost

別の関数から値を取得する関数は純粋と見なされますか?

それは、他の関数が何をするか、および呼び出し側関数が何をするかによって異なります。不純物は伝染性ですが、純度はそうではありません。

純粋な関数を呼び出しても、呼び出し元の関数の純度は変わりません。不純な関数を呼び出すと、呼び出し側の関数も不純になります。

したがって、あなたの例では、それはあなたが除外した部分の純粋さに依存します:それが純粋であれば、関数全体が純粋です。

これが純粋な関数である場合、代わりにグローバルDEFAULT_SEPARATOR定数を使用することとの違いは何ですか?

何もない。常に同じ値を返す関数は、定数と区別できません。実際、それは定数がλ計算でモデル化される方法とまったく同じです。

22
Jörg W Mittag

はい、これらは両方とも純粋な関数です(省略された部分も純粋であると想定しています)。

  1. 結果はパラメーターにのみ依存します。
  2. 副作用はありません。

getDefaultSeparator()が純粋な関数ではない場合、process()も純粋ではないことに注意してください。

JavaScriptでは、関数を再定義したり定数の値を変更したりするJavascriptの機能が回避されている限り、純粋な関数と定数のどちらを使用しても意味のある違いはありません。どちらも純粋な関数で使用できます。

純粋な関数の背後にある主要な概念は、プログラムの結果に影響を与えることなく、それらが返す値で置き換えることができるということです。

6
8bittree

他の人が言っているように、確かに、それはまだ純粋な機能です。

ただし、設計の問題について話しましょう。値を1か所に置くだけで、コードをDRYに保つために何かをしようとするのは正しいことです。さらに、私が考慮すべきことは、適切なカップリングのレベルです。

関数を使用すると、実装を変更する柔軟性が高まります。つまり、関数のアプローチでは、グローバル変数よりも疎結合になります。

問題は、それが必要かどうかです。

コンシューマーとプロバイダーが同じモジュール内にあり、プロバイダーがモジュールに対してプライベートである場合、プロバイダーがプライベート変数からaへのアップグレードを必要とする場合、このレベルの疎結合が必要であると主張することは困難です。プライベートメソッドでは、モジュール内の単純なリファクタリングをコンシューマに同時に適用できます。本当に必要になる前にメソッド/関数を使用すると、YAGNIに該当する可能性があります。

コンシューマーとプロバイダーが異なるモジュールにある場合でも、モジュールが一緒にバージョン管理されている(たとえば、コンシューマーとプロバイダーのモジュールが同じファイルにあるように、ミニファイアーを使用している)場合でも、YAGNIが適用されることがあります。

一方、たとえば、プロデューサーがコンシューマーとは別にバージョン管理されるライブラリ、APIパッケージ、またはモジュール内にある場合は、関数の使用が適切な場合があります。その場合、APIの寿命とOCPのような原則を検討する必要があります。

(別のメモでは、コードがかなりのサイズである場合、グローバル変数や関数ではなく、フィールドとメソッドを持つモジュールの使用をお勧めします。)

1
Erik Eidt