Reihenfolge der Parameter, um das Currying zu nutzen
93
Ich habe kürzlich zweimal Code überarbeitet, um die Reihenfolge der Parameter zu ändern, da zu viel Code vorhanden war, in dem Hacks gefallen flipoder \x -> foo bar x 42stattgefunden haben.
Welche Prinzipien helfen mir beim Entwerfen einer Funktionssignatur, das Currying optimal zu nutzen?
Für Sprachen, die Currying und Teilanwendung problemlos unterstützen, gibt es eine überzeugende Reihe von Argumenten, die ursprünglich von Chris Okasaki stammen:
Geben Sie die Datenstruktur als letztes Argument an
Manchmal werden alternative Argumente angegeben, um die Datenstruktur an die erste Stelle zu setzen, damit sie geschlossen werden kann, wodurch Funktionen für eine statische Struktur (z. B. Nachschlagen) erhalten werden, die etwas präziser sind. Der breite Konsens scheint jedoch zu sein, dass dies weniger ein Gewinn ist, zumal es Sie zu stark in Klammern gesetztem Code treibt.
Setzen Sie das unterschiedlichste Argument zuletzt
Bei rekursiven Funktionen wird häufig das Argument verwendet, das am stärksten variiert (z. B. ein Akkumulator), als letztes Argument, während das Argument, das am wenigsten variiert (z. B. ein Funktionsargument), am Anfang steht. Dies passt gut zum letzten Stil der Datenstruktur.
Eine Zusammenfassung der Okasaki-Ansicht finden Sie in seiner Edison-Bibliothek (wieder eine andere Datenstrukturbibliothek):
Teilanwendung : Argumente, die eher statisch sind, werden normalerweise vor anderen Argumenten angezeigt, um die Teilanwendung zu erleichtern.
Sammlung wird zuletzt angezeigt : In allen Fällen, in denen eine Operation eine einzelne Sammlung abfragt oder eine vorhandene Sammlung ändert, wird das Sammlungsargument zuletzt angezeigt . Dies ist so etwas wie ein De-facto-Standard für Haskell-Datenstrukturbibliotheken und verleiht der API ein gewisses Maß an Konsistenz.
Üblichste Reihenfolge : Wenn eine Operation eine bekannte mathematische Funktion für mehr als eine Datenstruktur darstellt, werden die Argumente so ausgewählt, dass sie mit der üblichsten Argumentreihenfolge für die Funktion übereinstimmen.
Geben Sie als Folge des ersten Aufzählungspunkts auch das Argument an, das möglicherweise zuletzt in einer Datenstruktur vorhanden ist. Es macht Karte, Falte und Freunde sauberer. tl; dr Sache in der Liste gehen zuletzt.
John F. Miller
1
Lookup kann sowieso nicht verkettet werden, daher unterstützt der erste Punkt dies nicht. haskell.org/haskellwiki/Parameter_order macht ein zwingendes Argument umgekehrt: "Da Objekte vom Typ Map Zuordnungen darstellen, ist es natürlich, eine Funktion zu haben, die ein Map-Objekt in die dargestellte Funktion umwandelt."
Brandon
11
Platzieren Sie die Argumente, die Sie am wahrscheinlichsten wiederverwenden, zuerst. Funktionsargumente sind dafür ein gutes Beispiel. Es ist viel wahrscheinlicher, dass map fSie zwei verschiedene Listen verwenden möchten , als dass Sie viele verschiedene Funktionen derselben Liste zuordnen möchten.
Wenn Sie tatsächlich viele Funktionen derselben Liste zuordnen, sollten Sie möglicherweise eine Liste von Funktionen und map ($myList)stattdessen diese Liste erstellen.
Tintenfisch
3
Ich neige dazu, das zu tun, was Sie getan haben, eine Bestellung auszuwählen, die gut erscheint, und dann umzugestalten, wenn sich herausstellt, dass eine andere Bestellung besser ist. Die Reihenfolge hängt stark davon ab, wie Sie die Funktion (natürlich) verwenden werden.
Platzieren Sie die Argumente, die Sie am wahrscheinlichsten wiederverwenden, zuerst. Funktionsargumente sind dafür ein gutes Beispiel. Es ist viel wahrscheinlicher, dass
map f
Sie zwei verschiedene Listen verwenden möchten , als dass Sie viele verschiedene Funktionen derselben Liste zuordnen möchten.quelle
map ($myList)
stattdessen diese Liste erstellen.Ich neige dazu, das zu tun, was Sie getan haben, eine Bestellung auszuwählen, die gut erscheint, und dann umzugestalten, wenn sich herausstellt, dass eine andere Bestellung besser ist. Die Reihenfolge hängt stark davon ab, wie Sie die Funktion (natürlich) verwenden werden.
quelle