Ich versuche herauszufinden, warum eine lokale Variable oder eine for-Schleife in einer Funktion nicht als reine funktionale Programmierung angesehen wird.
Angesichts dieser Funktion:
int as_int(char *str)
{
int acc; /* accumulate the partial result */
for (acc = 0; isdigit(*str); str++) {
acc = acc * 10 + (*str - '0');
}
return acc;
}
Unter welchen Umständen wäre die Variable acc ein Nebeneffekt? Selbst in einer gleichzeitigen Umgebung hätte jeder Aufruf der Funktion eine eigene Kopie von acc. Ich verstehe also nicht ganz, warum es in der funktionalen Programmierung nicht erlaubt ist.
functional-programming
loops
side-effect
Tomatenradar
quelle
quelle
as_int
ist eine reine Funktion, aber der Code darin ist nicht rein.acc
ist veränderlich.Antworten:
Looping in der funktionalen Programmierung ist nicht mit Steueranweisungen getan wie
for
undwhile
, es gemacht mit expliziten Aufrufen von Funktionen wiemap
,fold
oder Rekursion - all das beinhaltet den innere Schleife Anruf in einer anderen Funktion . Wenn der Schleifencode Variablen außerhalb der Schleife mutiert, manipuliert diese innere Schleifenfunktion Variablen außerhalb ihres Gültigkeitsbereichs und wäre daher unrein . Die gesamte äußere Funktion ist also rein, die Schleife jedoch nicht. Bei Schleifenkonstrukten in der funktionalen Programmierung müssen Sie den Status explizit angeben. Das Übersetzen Ihres Codes in etwas mit funktionalen Programmierschleifenwerkzeugen zeigt die Unreinheit:(Hinweis - Diese Syntax ist ungefähr, um die allgemeine Vorstellung zu vermitteln.)
Dieser Code verwendet eine innere Funktion für den Schleifenkörper, die die Variable mutieren muss
acc
, die außerhalb ihres Gültigkeitsbereichs liegt. Dies ist unrein - die Funktion der inneren Schleife hängt vom Kontext der äußeren Schleife ab . Wenn Sie sie mehrmals mit demselben Zeichen aufrufen, hat dies Nebenwirkungen, und die Reihenfolge, in der Sie sie in der Reihenfolge der Zeichen aufrufen, ist von Bedeutung. Um dies in der funktionalen Programmierung zu einer reinen Funktion zu machen, müssten Sie diese Abhängigkeit vom Zustand, der zwischen Schleifeniterationen übergeben wird, explizit machen mitfold
:fold
verwendet eine Funktion von zwei Argumenten für den inneren Schleifenkörper: Das erste Argument ist ein Element in der Sequenz, diefold
eine Schleife durchläuft, während das zweite ein Wert ist, den der innere Schleifenkörper verwendet, um Teilergebnisse aufzubauen. Für die erste Schleifeniterationacc
ist 0, für die zweiteacc
ist alles , was der erste Aufruf der inneren Schleifenfunktion zurückgegeben hat, für die dritte ist es, was auch immer die zweite innere Schleife zurückgegeben hat, und die letzte Schleife gibt das Ergebnis des gesamtenfold
Ausdrucks zurück.Beachten Sie, dass dies aus Sicht des restlichen Programms kein wirkliches Problem mit Ihrem Code darstellt - beide Definitionen von
as_int
sind rein. Der Unterschied besteht darin, dass Sie den Code der inneren Schleife zu einer reinen Funktion machen. Sie können die zahlreichen Tools nutzen, die die funktionale Programmierung bietet, um die Schleife in etwas Deklarativeres zu zerlegen (z. B. mithilfe von takeWhile, fold, filter, map usw. usw.).quelle
takeWhile
,fold
,filter
,map
, (dh deklarativen Stil) ist , dass Sie auch Stop - Denken in Bezug auf die „Compute etwas von destruktiv Aktualisierung Speicherplätze“. Auf diese Weise hängt das Ergebnis nicht von der Historie / genauen Reihenfolge der Berechnungsschritte ab.