Wird eine Funktion, die einen Wert von einer anderen Funktion erhält, als rein betrachtet?


9

Ich versuche herauszufinden, wie ich mit Standardvariablenwerten umgehen kann, wenn ich Funktionen ohne Nebenwirkungen mache, und habe Folgendes erreicht:

function getDefaultSeparator() {
    return ':';
}

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

    // Use separator in some logic

    return output;
}

Das Standardtrennzeichen wird in anderen Funktionen verwendet und ich möchte es nur an einer Stelle definieren.

Wenn dies eine reine Funktion ist, was ist der Unterschied zur Verwendung einer globalen DEFAULT_SEPARATOR-Konstante?


5
Es gibt keinen wesentlichen Unterschied, es sei denn, Sie möchten die Funktion als Platzhalter verwenden, damit später eine Logik hinzugefügt wird.
Robert Harvey

3
Mögliches Duplikat von Ist eine Funktion sofort unrein, wenn sie eine Funktion als Parameter verwendet? . Die Frage ist kein genaues Duplikat, aber die Antwort sollte dieselbe sein. ("Es hängt von der Reinheit der anderen Funktion ab.")
Jpmc26

1
Die Verwendung einer globalen Konstante macht eine Funktion nicht unrein. Die Verwendung eines globalen Werts, von dem Sie annehmen, dass er konstant ist, funktioniert.
Chepner

Übrigens können Sie Curry process(mit umgekehrter Parameterreihenfolge) und dann die Curry-Funktion aufvar processDefault = process(":")
Bob

Antworten:


22

Wird eine Funktion, die einen Wert von einer anderen Funktion erhält, als rein betrachtet?

Das hängt davon ab, was die andere Funktion tut und was die aufrufende Funktion tut. Unreinheit ist ansteckend, Reinheit nicht.

Das Aufrufen einer reinen Funktion ändert nichts an der Reinheit der aufrufenden Funktion. Das automatische Aufrufen einer unreinen Funktion macht die aufrufende Funktion ebenfalls unrein.

In Ihrem Beispiel hängt es also von der Reinheit des Teils ab, den Sie ausgelassen haben: Wenn das rein ist, ist die gesamte Funktion rein.

Wenn dies eine reine Funktion ist, was ist der Unterschied zur Verwendung einer globalen DEFAULT_SEPARATOR-Konstante?

Nichts. Eine Funktion, die immer den gleichen Wert zurückgibt, ist von einer Konstanten nicht zu unterscheiden. Genau so werden Konstanten im λ-Kalkül modelliert.


2
"Das automatische Aufrufen einer unreinen Funktion macht die aufrufende Funktion auch unrein" Sind Sie sich da ganz sicher? AFAICS, das Aufrufen einer unreinen Funktion macht den Anrufer nicht automatisch unrein, obwohl dies möglicherweise der Fall ist.
Deduplikator

2
@Deduplicator: hängt davon ab, wie viel statische Analyse Sie durchführen können (müssen). Sicher, wenn es eine Funktion gibt func, die Nebenwirkungen hat, wenn Sie 0 übergeben, aber nicht, wenn Sie 1 übergeben, können Sie vernünftigerweise sagen, dass funceine Funktion, die selbst "unrein" ist, diese als func(1)(und den Rückgabewert ignorierend) aufruft sagen) ist nicht unbedingt unrein. Das Anrufen funcreicht aus, um den Anrufer als potenziell unrein zu "beschmutzen", aber eine befleckte Funktion könnte sich auf irgendeine Weise als rein erweisen. Zumindest in Javascript, wo rein / unrein nicht in der Sprache definiert ist.
Steve Jessop

6

Ja, das sind beide reine Funktionen (vorausgesetzt, der elidierte Teil ist auch rein), weil:

  1. Das Ergebnis hängt nur von den Parametern ab.
  2. Es gibt keine Nebenwirkungen.

Beachten Sie, dass, wenn dies getDefaultSeparator()keine reine Funktion wäre, auch process()keine rein wäre.

In Javascript gibt es keinen bedeutenden Unterschied zwischen der Verwendung einer reinen Funktion oder einer Konstanten, und beide können von einer reinen Funktion verwendet werden, solange die Fähigkeit von Javascript, Funktionen neu zu definieren oder die Werte von Konstanten zu ändern, vermieden wird.

Ein Schlüsselkonzept hinter reinen Funktionen ist, dass sie durch den Wert ersetzt werden können, den sie zurückgeben, ohne die Ergebnisse des Programms zu beeinflussen.


1

Wie die anderen sagen, ist es sicher immer noch eine reine Funktion.

Lassen Sie uns jedoch über die Designprobleme sprechen. Sie haben Recht, etwas zu tun, um den Code TROCKEN zu halten, indem Sie den Wert nur einmal eingeben. Darüber hinaus sollte meines Erachtens auch das angemessene Maß an Kopplung berücksichtigt werden.

Die Verwendung einer Funktion bietet Ihnen mehr Flexibilität beim Ändern der Implementierung, dh, der Funktionsansatz bietet eine lockerere Kopplung als eine globale Variable.

Die Frage ist, ob man es braucht oder nicht?

Wenn sich Verbraucher und Anbieter im selben Modul befinden und der Anbieter für das Modul privat ist, ist es schwer zu argumentieren, dass diese Ebene der losen Kopplung erforderlich ist, da der Anbieter ein Upgrade von einer privaten Variablen auf eine benötigt Bei einer privaten Methode kann gleichzeitig ein einfaches Refactoring innerhalb des Moduls auf die Verbraucher angewendet werden. Die Verwendung einer Methode / Funktion, bevor Sie sie wirklich benötigen, kann unter YAGNI fallen.

Selbst wenn sich Verbraucher und Anbieter in unterschiedlichen Modulen befinden, die Module jedoch zusammen versioniert sind (z. B. verwenden Sie einen Minifyer, sodass sich die Module von Verbrauchern und Anbieter in derselben Datei befinden), kann YAGNI ebenfalls angewendet werden.

Befindet sich der Produzent beispielsweise in einem Bibliotheks- oder API-Paket oder -Modul, das separat von den Verbrauchern versioniert ist, kann die Verwendung der Funktion angemessen sein. In diesem Fall sollten wir uns die Langlebigkeit der API und Prinzipien wie OCP ansehen.

(Wenn Ihr Code eine signifikante Größe hat, würde ich die Verwendung von Modulen mit Feldern und Methoden anstelle globaler Variablen und Funktionen empfehlen.)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.