Laut Wikipedia:
In der Computerprogrammierung kann eine Funktion als rein beschrieben werden, wenn beide Aussagen über die Funktion gelten: Die Funktion wertet immer den gleichen Ergebniswert bei gleichen Argumentwerten aus. Der Funktionsergebniswert kann weder von versteckten Informationen oder Zuständen abhängen, die sich im Verlauf der Programmausführung oder zwischen verschiedenen Programmausführungen ändern können, noch von externen Eingaben von E / A-Geräten. Die Auswertung des Ergebnisses verursacht keine semantisch beobachtbaren Nebenwirkungen oder Ausgaben, wie z. B. die Mutation veränderlicher Objekte oder die Ausgabe an E / A-Geräte.
Ich frage mich, ob es möglich ist, eine Funktion zu schreiben, die berechnet, ob eine Funktion rein ist oder nicht. Beispielcode in Javascript:
function sum(a,b) {
return a+b;
}
function say(x){
console.log(x);
}
isPure(sum) // True
isPure(say) // False
if (rand(1000000)<2) return WRONG_ANSWER
, hilft es nicht, die Funktion viele Male auf ein konsistentes Verhalten zu prüfen. Wenn Sie jedoch Zugriff auf die Funktionsdefinition haben, ist der Beweis trivial.say
Anrufe,console.log
die unreinsay
sind, auch unrein.Antworten:
Ja, das ist je nach Sprache möglich.
In JavaScript können Sie anhand der folgenden Kriterien feststellen, ob eine Funktion rein ist:
Es werden nur Parameter und Einheimische gelesen.
Es schreibt nur Einheimische;
Bei Nicht-Einheimischen werden nur reine Funktionen aufgerufen.
Alle Funktionen, die implizit aufgerufen werden, sind rein, z
toString
. undEs werden nur Eigenschaften von Einheimischen geschrieben, wenn sie keine Nicht-Einheimischen als Alias verwenden.
Aliasing kann im allgemeinen Fall in JavaScript nicht ermittelt werden, da Sie die Eigenschaften eines Objekts immer dynamisch nachschlagen können (
object["property"]
). Vorausgesetzt, Sie tun das nie und Sie haben die Quelle des gesamten Programms, dann denke ich, dass das Problem nachvollziehbar ist. Sie benötigen außerdem Informationen darüber, welche nativen Funktionen Nebenwirkungen haben, z. B.console.log
oder fast alles, was das DOM betrifft.Der Begriff „rein“ könnte auch einer Klarstellung bedürfen. Selbst in einer stark statisch typisierten, rein funktionalen Programmiersprache, in der alle Funktionen referenziell transparent sind, kann eine Funktion immer noch nicht beendet werden. Wenn wir also darüber sprechen
id :: a -> a
, sagen wir wirklich nicht:Sondern:
Weil eine gültige Implementierung von
id
isterror "Not implemented!"
. Wie Peteris betont, könnte diese Nichttotalität als eine Art Verunreinigung angesehen werden. Koka ist eine funktionale Programmiersprache mit einer auf JavaScript modellierten Syntax, die auf mögliche Auswirkungen wie Divergenz (Nichtterminierung), referenzielle Transparenz, Auslösen von Ausnahmen und E / A-Aktionen schließen kann.quelle
toString
es für ein Objekt, das Sie als Zeichenfolge verwenden, rein ist.function a (o) { return o.method(); }
- Wir können dies nicht beantworten, da es davon abhängt, welcher Parameter übergebeno
wird. Wir können auch nicht berücksichtigen, was passiert, wenn eine zuvor zertifizierte reine Funktion in eine nicht reine Implementierung geändert wird, was bei Javascript immer ein potenzielles Problem darstellt.Nein. Sie können leicht überprüfen, ob eine Funktion nur "rein sichere" Operationen ausführt, wie in Jon Purdys Antwort beschrieben, aber das ist IMO nicht genug, um die Frage zu beantworten.
Betrachten Sie diese Funktion:
Wenn
someCheck
es unrein ist, ist es natürlich auch sopossiblyPure
. Aber wennsomeCheck
es rein ist undtrue
für jeden möglichen Wert von zurückgibtx
,possiblyPure
ist es rein, da der unreine Codepfad nicht erreichbar ist!Und hier kommt der schwierige Teil: Bestimmen, ob
someCheck
für jede mögliche Eingabe true zurückgegeben wird oder nicht . Der Versuch, diese Frage sofort zu beantworten, führt Sie in den Bereich des Halteproblems und ähnlicher unentscheidbarer Probleme.EDIT: Beweis, dass es unmöglich ist
Es besteht eine gewisse Unsicherheit, ob eine reine Funktion bei jeder möglichen Eingabe enden muss oder nicht. In beiden Fällen kann das Stoppproblem jedoch verwendet werden, um zu zeigen, dass die Reinheitsprüfung unmöglich ist.
Fall A) Wenn eine reine Funktion erforderlich ist , jede mögliche Eingabe zu beenden, du hast , um das Halteproblem zu lösen , um zu bestimmen , ob die Funktion rein ist. Da bekannt ist, dass dies unmöglich ist, kann nach dieser Definition die Reinheit nicht berechnet werden.
Fall B) Wenn eine reine Funktion bei einigen Eingaben nicht enden darf, können wir so etwas konstruieren: Nehmen wir an, dass
isPure(f)
computes iff
eine Zeichenfolge ist, die eine reine Funktion definiert.Jetzt
isPure
muss festgestellt werden, ob dief
Eingabe an der eigenen Quelle angehalten wird oder nicht . Wenn es anhält,upf
ist es unrein; Wenn es nicht endet,upf
ist es rein, wennf
es rein ist.Wenn es
isPure
wie erwartet funktioniert hätte (liefert korrekte Ergebnisse und wird bei jeder Eingabe beendet), hätten wir das Stoppproblem (*) gelöst! Da dies als unmöglich bekannt ist,isPure
kann es nicht existieren.(*) für reine JavaScript-Funktionen, was ausreicht, um es auch für die Turingmaschine zu lösen.
quelle
Diese Stackoverflow-Frage hat eine Antwort von yfeldblum, die hier relevant ist. (Und hat aus irgendeinem Grund eine Ablehnung, die ich nicht ergründen kann. Wäre es eine schlechte Etikette, etwas zu bewerten, das 3 Jahre alt ist?) Er gibt in einem Kommentar den Beweis, dass die Frage, ob eine Funktion rein ist, auf das Problem des Anhaltens reduziert werden kann.
Ich denke, aus praktischer Sicht wäre es für einige Sprachen nicht allzu schwierig, wenn Sie die Funktion ja, nein oder vielleicht zurückgeben lassen. Ich habe vor ein paar Tagen ein Video über Clojure gesehen, und der Sprecher hatte eine Reihe von Verunreinigungen in einer Codebasis gezählt, indem er nach ungefähr 4 verschiedenen Zeichenfolgen gesucht hatte (wie "ref"). Aufgrund der Betonung von Clojure auf Reinheit und Trennung unreiner Dinge war es trivial, aber es war nicht genau das, wonach Sie suchen.
Theoretisch unmöglich, praktisch möglich, wenn Sie die Frage ein wenig optimieren, und ich denke, wie schwer es sein würde, hängt stark von der Sprache ab. Einfachere / sauberere Sprachen mit Schwerpunkt auf Unveränderlichkeit und guter Reflexion wären einfacher.
quelle
bottom
ist ein gültiger, erstklassiger Wert, der es nicht verdient, auf diese Weise diskriminiert zu werden.Gute Frage.
Das Beste, was Sie in der Praxis tun können, vorausgesetzt, Sie können keine E / A-Aktionen abhören, um die Funktion so oft wie möglich aufzurufen. Überprüfen Sie dann, ob der Rückgabewert konsistent ist.
Dies ist jedoch im Allgemeinen nicht möglich. Nicht anhaltende Programme sind wohl nicht rein, und wir können das Problem des Anhaltens nicht entscheiden.
quelle
void
wäre jede Funktion "rein", was eindeutig falsch ist.Im allgemeinen Fall nicht möglich. Siehe Problem beim Anhalten . Kurz gesagt, es ist unmöglich, ein Programm zu schreiben, das bei einer beliebigen Funktion und Eingabe bestimmt, ob das Programm für immer angehalten oder ausgeführt wird. Wenn es für immer läuft, ist es keine reine Funktion , die der von Ihnen angegebenen Definition entspricht.
quelle
bottom
Wert ausgewertet .