Fold
(aka reduce
) wird als eine sehr wichtige Funktion höherer Ordnung angesehen. Map
kann in fold
ausgedrückt werden ( siehe hier ). Aber es klingt für mich akademischer als praktisch. Eine typische Verwendung könnte darin bestehen, die Summe, das Produkt oder das Maximum von Zahlen zu erhalten, aber diese Funktionen akzeptieren normalerweise eine beliebige Anzahl von Argumenten. Warum also (fold + 0 '(2 3 5))
schreiben, wenn (+ 2 3 5)
gut funktioniert. Meine Frage ist, in welcher Situation ist es am einfachsten oder am natürlichsten, fold
zu benutzen?
Der Punkt von fold
ist, dass es abstrakter ist. Es ist nicht so, dass du Dinge tun kannst, die du vorher nicht tun konntest, es ist, dass du sie leichter machen kannst.
Mit fold
können Sie die Funktion any verallgemeinern, die für zwei Elemente definiert ist, um sie auf eine beliebige Anzahl von Elementen anzuwenden. Dies ist ein Gewinn, da es normalerweise viel einfacher ist, eine einzelne Funktion zu schreiben, zu testen, zu warten und zu modifizieren, die zwei Argumente anwendet als eine Liste. Und es ist immer einfacher zu schreiben, zu testen, zu warten, usw. Eine einfache Funktion anstelle von zwei mit ähnlicher aber nicht ganz funktionierender Funktionalität.
Da fold
(und in diesem Fall map
, filter
und Freunde) ein wohldefiniertes Verhalten haben, ist es oft viel einfacher, Code zu verstehen, der diese Funktionen als explizite Rekursion verwendet.
Grundsätzlich, sobald Sie die eine Version haben, erhalten Sie die andere "kostenlos". Letztendlich machst du weniger Arbeit, um das gleiche Ergebnis zu erzielen.
Hier sind ein paar einfache Beispiele, wo reduce
wirklich gut funktioniert.
Ermitteln Sie die Summe der Maximalwerte jeder Unterliste
Clojure:
%Vor%Schläger:
%Vor%Erstellen Sie eine Karte aus einer Liste
Clojure:
%Vor% Für ein komplizierteres Clojure-Beispiel mit reduce
finden Sie meine Lösung für Project Euler-Probleme 18 & amp; 67 .
Siehe auch: reduzieren vs. anwenden
Ihr Beispiel (+ 2 3 4
) funktioniert nur, weil Sie vorher die Anzahl der Argumente kennen. Falten funktionieren auf Listen, deren Größe variieren kann.
fold
/ reduce
ist die allgemeine Version des "cdr-down down a list" -Musters. Jeder Algorithmus, der in der Reihenfolge jedes Element einer Sequenz verarbeitet und daraus einen Rückgabewert berechnet, kann damit ausgedrückt werden. Es ist im Grunde die funktionale Version der foreach-Schleife.
In allgemeinen Lisp-Funktionen akzeptieren keine Anzahl von Argumenten.
In jeder Common Lisp-Implementierung ist eine Konstante definiert CALL-ARGUMENTS-LIMIT , die 50 oder größer sein muss.
Dies bedeutet, dass jede solche portabel geschriebene Funktion mindestens 50 Argumente akzeptieren sollte. Aber es könnte nur 50 sein.
Diese Grenze existiert, damit Compiler möglicherweise optimierte Aufrufschemata verwenden und nicht den allgemeinen Fall angeben, bei dem eine unbegrenzte Anzahl von Argumenten übergeben werden könnte.
Um also große (mehr als 50 Elemente) Listen oder Vektoren im portablen Common-Lisp-Code zu verarbeiten, ist es notwendig Iterationskonstrukte zu verwenden, zu reduzieren, zu kartieren und ähnliches. Daher ist es auch notwendig, (apply '+ large-list)
nicht zu verwenden, sondern (reduce '+ large-list)
.
Code mit Falte ist in der Regel umständlich zu lesen. Aus diesem Grund bevorzugen die Nutzer Karte, Filter, Existieren, Summe und so weiter - sofern verfügbar. Heute schreibe ich hauptsächlich Compiler und Interpreten; Hier sind einige Möglichkeiten, die ich benutze:
Was all diese Anwendungen gemeinsam haben, ist, dass sie Informationen über eine Sequenz in einer Art Gruppe oder Wörterbuch sammeln. Sehr praktisch.
Hier ist ein Beispiel, das noch niemand erwähnt hat.
Wenn Sie eine Funktion mit einer kleinen, klar definierten Schnittstelle wie "fold" verwenden, können Sie diese Implementierung ersetzen, ohne die Programme zu unterbrechen, die sie verwenden. Sie könnten zum Beispiel eine verteilte Version erstellen, die auf tausenden von PCs läuft , so dass ein Sortieralgorithmus verwendet wird, der diese verwendet eine verteilte Sortierung und so weiter. Ihre Programme werden robuster, einfacher und schneller .
> Ihr Beispiel ist ein triviales: +
nimmt bereits eine beliebige Anzahl von Argumenten, läuft schnell in wenig Speicher und wurde bereits von jedem, der Ihren Compiler geschrieben hat, geschrieben und debuggt. Diese Eigenschaften sind oft nicht zutreffend für Algorithmen, die ich ausführen muss.
Tags und Links functional-programming lisp fold reduce