In OCaml, was ist die kanonische Art des Abgleichs mit mehreren Argumenten einer Funktion?

8

Sie könnten Mustervergleiche mit mehreren Argumenten einer Funktion durchführen, indem Sie ein Tupel erstellen und es dann in einem Übereinstimmungsausdruck destrukturieren:

%Vor%

Alternativ können Sie, wenn Sie keine Curry-Funktion benötigen, f als einziges Argument ein Tupel verwenden:

%Vor%

Der Vorteil der letzteren Methode besteht darin, dass Sie die Argumente bei jeder Definition einer Funktion nicht zweimal schreiben müssen. Aber Funktionen, die ein Tupel nehmen, scheinen nicht so populär zu sein wie curierte.

Also, welcher der beiden gilt in der OCaml-Community als kanonisch oder bevorzugt?

BEARBEITEN: Genau wie das Pad unten gezeigt hat, meine ich let f = function blah blah im zweiten Code-Snippet.

    
Pteromys 27.11.2011, 13:46
quelle

4 Antworten

8

Ein Tupel ist nicht nur ein syntaktisches Konstrukt, es repräsentiert eine echte Datenstruktur. Dies bedeutet, dass fun (x,y) (sehr geringfügig) weniger effizient ist als f x y in dem Fall, in dem x und y nicht bereits geupdated sind, weil ein Tupel zugewiesen werden muss. Wenn das nicht klar ist, wäre das grobe Äquivalent in Java

%Vor%

Aus diesem Grund ist es im Allgemeinen vorzuziehen, Tupel als Funktionsargumente zu verwenden, es sei denn, Sie haben einen guten Grund dafür.

P.S. Eine ähnliche Überlegung gilt für Datentypdeklarationen, bei denen sich die folgenden subtil unterscheiden:

%Vor%

Foo ist ein Datentypkonstruktor, der zwei Argumente akzeptiert. Bar ist ein Konstruktor, der ein Argument (ein Tupel) akzeptiert.

    
Chris Conway 27.11.2011, 15:35
quelle
9

Diese Lösung ist kanonisch:

%Vor%

Der Compiler optimiert diesen Spezialfall und weist dem Tupel (x, y) nicht wirklich einen Block zu.

    
Martin Jambon 27.11.2011 18:41
quelle
5

Tatsächlich ist f = function... eine Abkürzung von f (x, y) = match (x, y) with... so:

%Vor%

ist dasselbe wie:

%Vor%

(Beachten Sie, dass in Ihrer zweiten Formulierung ein Fehler vorliegt; diese beiden Versionen sind nicht kompatibel).

Wie Sie bereits erwähnt haben, kann man nicht vermeiden, match ... with... in einer Curry-Funktion zu verwenden. Persönlich bevorzuge ich die Curry-Form einer Funktion, da diese flexibler ist, insbesondere bei partieller Anwendung. Außerdem wird der Mustervergleich nicht nur in Funktionsargumenten angewendet. Sie werden im Wesentlichen überall in OCaml verwendet, was match ... with... construct noch wichtiger macht.

Wenn Sie das Nutzungsmuster wie oben sehen, versuchen Sie, match ... with... durch function zu ersetzen. Es ist nur eine Frage des Stils, so dass hier nichts mehr bevorzugt wird.

    
pad 27.11.2011 14:21
quelle
3

Der kanonische Weg ist eine Curry-Funktion und zu match auf dem Tupel, d. h. dein erstes Snippet.

Auf diese Weise wird die Standardbibliothek geschrieben (sehen Sie sich die Quellen der Standardbibliothek an, zum Beispiel viele Funktionen in list.ml ).

Dies ist auch die Art und Weise, auf die die Implementierung optimiert ist, insbesondere der native Code-Compiler. Wenn Sie ein Tupel oder einen anderen Block erstellen und es sofort zerstören, ohne es an Funktionen zu übergeben, die einen Block erwarten, erkennt der Compiler für den systemeigenen Code das oft und vermeidet die Zuweisung eines Blocks. Selbst wenn Sie am Ende einen Block zuweisen, ist es effizienter, die Dauer des Blocks so kurz wie möglich zu halten, um die Wahrscheinlichkeit zu erhöhen, dass der Block im Minor-Heap und im Prozessor-Cache verbleibt.

    
Gilles 27.11.2011 19:15
quelle

Tags und Links