Da die Reinheit eines Eingabeparameters bis zur Laufzeit unbekannt ist, wird eine Funktion sofort als unrein angesehen, wenn sie eine Funktion als Eingabeparameter verwendet?
Verwandte: Wenn eine Funktion eine reine Funktion anwendet, die außerhalb der Funktion definiert, aber nicht als Parameter übergeben wird, ist sie dann immer noch rein, wenn sie die Kriterien erfüllt, keine Nebenwirkungen zu haben, und die Ausgabe ausschließlich von der Eingabe abhängt?
Für den Kontext schreibe ich funktionalen Code in JavaScript.
functional-programming
pure-function
Dancrumb
quelle
quelle
foo = function(function bar){ print(bar.toString()) }
foo = function(function bar) { return 3; }
ist rein und nimmt eine Funktion als Argument an.toString()
(dh den, den Sie auf Javas Objekt finden würden).Antworten:
Solange alle in der Funktion verwendeten Werte ausschließlich durch ihre Parameter definiert sind, handelt es sich um eine reine Funktion.
Die Facette, dass die Ausgabe jedes Mal für dieselbe Eingabe dieselbe ist, wird dadurch gesteuert, ob die Parameter rein sind. Wenn Sie annehmen, dass die Parameter (wie ein Funktionsargument) ebenfalls rein sind, dann ist es rein.
In einer Sprache wie Javascript, in der Reinheit nicht erzwungen wird, bedeutet dies, dass es möglich ist, eine ansonsten reine Funktion unrein zu machen, indem eine unreine Funktion aufgerufen wird, die als Parameter übergeben wird.
Dies bedeutet effektiv, dass es für Sprachen, die keine (dh fast alle) Reinheit erzwingen, unmöglich ist, eine reine Funktion zu definieren, die als Argumente übergebene Funktionen aufruft. Es ist immer noch nützlich, sie so rein wie möglich zu schreiben und sie als reine Funktionen zu betrachten, aber Sie müssen vorsichtig sein, denn die Annahme, dass sie rein ist, wird durch falsche Argumente zerstört.
Nach meiner Erfahrung in der Praxis ist dies normalerweise keine große Sache - ich finde es selten, dass unreine Funktionen als Funktionsargumente für reine Funktionen verwendet werden.
quelle
areaOfCircle r => Math.Pi * r * r
, wird sieareaOfCircle
nicht rein, da sie nicht nur Parameter verwendet?f(f2)
, die aufgerufenf2
wird, nicht transitiv auf irgendetwasf2
angewiesen ist. Eine Funktion, die möglicherweise beliebige übergebene Funktionen aufruft, ist nicht rein.function compose(f, g) {return function h(x) {return f(g(x));};}
, das rein ist, obwohl es Funktionen als Argumente nimmt.find
Routine ein unreines Prädikat übergeben, das für das dritte übereinstimmende Element, auf das sie trifft, "true" zurückgibt, oder einen solchen Unsinn.Gegenbeispiel:
Es spielt keine Rolle, ob
other_function
es sich um eine reine Funktion, eine unreine Funktion oder gar keine Funktion handelt. Diepure
Funktion ist rein.Anderes Gegenbeispiel:
Diese Funktion ist rein, auch wenn
x
es sich um eine unreine Funktion handelt.identity(impure_function)
wird immer zurückkehrenimpure_function
, egal wie oft Sie den Anruf wiederholen. Es spielt keine Rolle, obidentity(impure_function)()
immer dasselbe zurückgegeben wird. Der Rückgabewert einer Funktion hat keinen Einfluss auf ihre Reinheit.Wenn eine Funktion eine Funktion aufruft, die als Argument übergeben wurde, ist sie im Allgemeinen nicht rein. Zum Beispiel ist eine Funktion
function call(f) {f();}
nicht rein, weil sie, obwohl sie keinen globalen oder veränderlichen Zustand erwähnt,f
so etwas wiealert
sichtbare Nebenwirkungen hervorrufen kann.Wenn eine Funktion Funktionen als Argumente verwendet, diese aber nicht aufruft oder aufruft, kann sie rein sein. Es könnte immer noch unrein sein, wenn es eine andere unreine Sache tut. Zum Beispiel
function f(ignored_function) {alert('This isn't pure.');}
ist unrein, obwohl es nie anruftignored_function
.quelle
Technisch gesehen ja, es sei denn, es gibt in Ihrer Sprache Möglichkeiten, um sicherzustellen, dass die Eingabefunktion auch rein ist.
Ja. Konzentrieren wir uns also darauf, worauf es ankommt. Eine Funktion pur aufzurufen oder nicht, ist an und für sich nicht sinnvoll. Reine Funktionen sind nützlich, da das Erzeugen der gleichen Ausgabe für jede Eingabe und unabhängig vom Status oder mit Nebenwirkungen eine sehr nützliche Eigenschaftsgruppe ist. Sobald Ihre Funktion ausgeführt wurde, können Sie sich die Antwort für diese Eingabe "merken" und sie ist immer wahr. Sie müssen die Funktion auch nicht erneut ausführen, um Nebenwirkungen zu erzeugen. Und Sie können diese Funktion parallel (oder außer Betrieb) mit anderen Funktionen ausführen und wissen, dass sie keine versteckten Interaktionen haben, die sich schlecht verhalten.
Diese nützlichen Eigenschaften bleiben erhalten, wenn die Funktion andere reine Nur-Lese-Funktionen verwendet, unabhängig davon, wie auf sie verwiesen wird.
quelle
Wie Telastyn sagte: Technisch gesehen ja, es sei denn, es gibt einen Weg in Ihrer Sprache, um sicherzustellen, dass die Eingabefunktion auch rein ist.
Das ist nicht hypothetisch, es gibt in der Tat gute Möglichkeiten, dies zu garantieren. Zumindest in einer stark typisierten Sprache.
So eine reine ~ Funktion würden Sie in JavaScript als schreiben
kann direkt nach Haskell übersetzt werden:
Jetzt können Sie in JavaScript böse Dinge tun wie
Dies ist in Haskell nicht möglich . Der Grund dafür ist, dass etwas nebenwirkungsreiches
console.log()
immer einen Ergebnistyp haben mussIO something
, nicht nursomething
alleine.Für diesen Ausdruck typecheck, müssten wir geben
foo
die Art UnterschriftEs stellt sich aber heraus, dass ich es dann nicht mehr implementieren kann: Da die Argumentfunktion
IO
das Ergebnis hat, kann ich es nicht innerhalb verwendenfoo
.Die einzige Möglichkeit, in der ich eine
IO
Aktion verwenden könnte,foo
ist, wenn das Ergebnis vonfoo
den TypIO Int
selbst hat:Aber an dieser Stelle wird aus der Signatur deutlich,
foo
dass es sich auch nicht um eine reine Funktion handelt.quelle
unsafeIO
:-)IO
. Übrigens kann es auch verwendet werden, um Chaos zu verursachen, indem Nebenwirkungen in einer "reinen" Funktion ausgeblendet werden. Dies ist in Haskell jedoch sehr unsicher, da es keinen wirklich zuverlässigen Weg gibt, die Auswertungsreihenfolge von reinen Funktionen anzugeben.unsafeIO
; Dies ist eine Notausstiegsluke, die das Typsystem garantiert umgeht, und daher ist Ihre keine gute Sache.Nein ist es nicht.
Wenn die übergebene Funktion unrein ist UND Ihre Funktion die übergebene Funktion aufruft, wird Ihre Funktion als unrein betrachtet.
Die reine / unreine Beziehung ist ein bisschen wie Sync / Async in JS. Sie können reinen Code von unreinen frei verwenden, aber nicht umgekehrt.
quelle