2009-12-03 11 views
65

Sorry über die vagen Titel, aber ein Teil dieser Frage ist, was diese beiden Syntax Stile werden genannt:F # explizite Spiel vs Funktion Syntax

let foo1 x = 
    match x with 
    | 1 -> "one" 
    | _ -> "not one" 

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one" 

Der andere Teil ist das, was Unterschied zwischen den beiden ist, und wenn Ich möchte das eine oder andere benutzen?

Antwort

40

Das Spiel Version ist ein "Pattern-Matching-Ausdruck" genannt. Die Funktionsversion wird als "Pattern-Matching-Funktion" bezeichnet. Gefunden in Abschnitt 6.6.4 der spec.

Die Verwendung übereinander ist eine Frage des Stils. Ich bevorzuge nur die Funktion Version, wenn ich eine Funktion definieren muss, die nur eine Übereinstimmungserklärung ist.

10

Sie tun das gleiche in Ihrem Fall - das Schlüsselwort function wirkt wie eine Kombination aus dem Schlüsselwort fun (um ein anonymes Lambda zu erzeugen), gefolgt vom Schlüsselwort match.

Technisch diese beiden sind die gleichen, mit dem Zusatz eines fun:

let foo1 = fun x -> 
    match x with 
    | 1 -> "one" 
    | _ -> "not one" 

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one" 
+1

Ist es nicht anders herum - also 'Fun' ist technisch definiert in Bezug auf' Funktion | _ -> ... '? –

+1

Um genau zu sein, 'Spaß x y -> ...' wäre 'Spaß x -> Spaß y -> ...', und dann 'Spaß x -> ...' wäre 'Funktion | x -> ... '. Deshalb können Sie in 'fun' Mustervergleiche vornehmen - z. 'Spaß (x :: xs) -> ...'. –

2

Die beiden Syntaxen gleichwertig sind. Die meisten Programmierer wählen das eine oder das andere und verwenden es dann konsequent.

Die erste Syntax bleibt besser lesbar, wenn die Funktion mehrere Argumente akzeptiert, bevor sie mit der Arbeit beginnt.

59

Das Pro für die zweite Syntax ist, dass wenn es in einem Lambda verwendet wird, es etwas knapper und lesbarer sein könnte.

List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1] 

vs

List.map (function 1 -> "one" | _ -> "not one") [0;1;2;3;1] 
14

Die Funktionsversion ist ein Kurzzeichen für die vollständige Übereinstimmungssyntax im Sonderfall, in dem die Match-Anweisung die gesamte Funktion ist und die Funktion nur ein einziges Argument hat (Tupel zählen als eins). Wenn Sie zwei Argumente haben möchten, müssen Sie die vollständige Übereinstimmungssyntax * verwenden. Sie können dies in den Typen der folgenden zwei Funktionen sehen.

//val match_test : string -> string -> string 
let match_test x y = match x, y with 
         | "A", _ -> "Hello A" 
         | _, "B" -> "Hello B" 
         | _ -> "Hello ??" 

//val function_test : string * string -> string     
let function_test = function 
         | "A", _ -> "Hello A" 
         | _, "B" -> "Hello B" 
         | _ -> "Hello ??" 

Wie Sie sehen können, benötigt die Match-Version zwei separate Argumente, während die Funktionsversion ein einzelnes Tupel-Argument benötigt. Ich benutze die Funktionsversion für die meisten einzelnen Argumentfunktionen, da ich finde, dass die Funktionssyntax sauberer aussieht.

* Wenn Sie wirklich wollten, können Sie die Funktionsversion erhalten, um die richtige Art Unterschrift zu haben, aber es sieht meiner Meinung nach ziemlich hässlich aus - siehe Beispiel unten.

//val function_match_equivalent : string -> string -> string 
let function_match_equivalent x y = (x, y) |> function 
               | "A", _ -> "Hello A" 
               | _, "B" -> "Hello B" 
               | _ -> "Hello ??" 
6

Nur der Vollständigkeit halber willen, ich habe gerade auf Seite 321 von Expert FSharp.

„Hinweis, Listing 02.12 verwendet die Ausdrucksform function pattern-rules -> expression Dies entspricht (fun x -> match x with pattern-rules -> expression) und ist besonders praktisch, da eine Möglichkeit, Funktionen zu definieren, die direkt über diskriminierte Gewerkschaften arbeiten."

4

Funktion erlaubt nur ein Argument für sondern ermöglicht Pattern-Matching, während Spaß die allgemeine und flexible Art und Weise ist eine Funktion zu definieren Werfen Sie einen Blick hier:. http://caml.inria.fr/pub/docs/manual-ocaml/expr.html

+0

Warum sagst du nur 1 Argument statt nur das letzte Argument? Es ist möglich, mehr als 1 Argument zu haben und "Funktion" zu verwenden. Ist das eine Interpretation der Funktion höherer Ordnung? – symbiont

0

Dies ist ein alte Frage, aber ich werde meinen $ 0,02.

im allgemeinen ich mag besser die match Version, da ich von der Python Welt kommen, wo werfen „explicit ist besser als implizit.“

Wenn die Typinformation des Parameters benötigt wird, kann natürlich die function Version nicht verwendet werden.

OTOH Ich mag das Argument von Stringer gemacht, so dass ich anfangen werde, function in einfachen Lambdas zu verwenden.