Praktischer Einsatz von falten / reduzieren in funktionalen Sprachen

8

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?

    
Adam Schmideg 16.03.2011, 21:05
quelle

6 Antworten

12

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.

    
Ezra 16.03.2011, 21:28
quelle
8

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

    
dbyrne 16.03.2011 21:27
quelle
4
  1. Ihr Beispiel (+ 2 3 4 ) funktioniert nur, weil Sie vorher die Anzahl der Argumente kennen. Falten funktionieren auf Listen, deren Größe variieren kann.

  2. 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.

Rörd 16.03.2011 22:36
quelle
4

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) .

    
Rainer Joswig 18.03.2011 09:18
quelle
3

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:

  • Berechnen Sie die Menge der freien Variablen für eine Funktion, einen Ausdruck oder einen Typ
  • Fügen Sie der Symboltabelle die Parameter einer Funktion hinzu, z. B. für die Typprüfung
  • Sammeln Sie die Sammlung aller sinnvollen Fehlermeldungen, die aus einer Folge von Definitionen generiert wurden
  • Hinzufügen aller vordefinierten Klassen zu einem Smalltalk-Interpreter beim Booten

Was all diese Anwendungen gemeinsam haben, ist, dass sie Informationen über eine Sequenz in einer Art Gruppe oder Wörterbuch sammeln. Sehr praktisch.

    
Norman Ramsey 17.03.2011 01:46
quelle
2

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.

    
Ken 16.03.2011 22:45
quelle