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


9

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

function getDefaultSeparator() {
    return ':';
}

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

    // Use separator in some logic

    return output;
}

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

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


5
後で追加するロジックのプレースホルダーとして関数を使用する予定がない限り、重要な違いはありません。
Robert Harvey

3
可能性の重複された直後に不純それがパラメータとしての機能を取る場合、関数?。質問は完全に重複しているわけではありませんが、答えは同じでなければなりません。(「他の関数の純度に依存します。」
jpmc26 '14

1
グローバル定数を使用しても、関数が不純になることはありません。定数であると想定するグローバル値を使用することはできます。
chepner 2016年

ところで、カレーprocess(パラメータの順序を逆にして)して、カレー機能を特殊化することができますvar processDefault = process(":")
bob

回答:


22

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

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

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

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

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

何もない。常に同じ値を返す関数は、定数と区別できません。実際、それは定数がλ計算でどのようにモデル化されるかということです。


2
「不純な関数を呼び出すと、呼び出し関数も不純になります」そのことについて、本当に確信がありますか?AFAICS、不純な関数を呼び出しても、呼び出し元が不純になることはありませんが、そうすることはできます。
デュプリケータ

2
@Deduplicator:(気になる)静的分析の量に依存します。確かに、func0を渡したときに副作用があるが1を渡したときに副作用がないfunc関数がある場合、それ自体は「不純」であるにもかかわらず、それを次のように呼び出すfunc(1)(そして戻り値を無視して、言う)必ずしも不純ではありません。呼び出しfuncは、呼び出し元を潜在的に不純であると「汚染」するのに十分ですが、汚染された関数は、結局のところ純粋であることを証明できる場合があります。少なくともJavaScriptでは、純粋/不純が言語内で定義されていません。
Steve Jessop 2016年

6

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

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

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

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

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


1

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

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

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

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

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.