2009-12-03 6 views
65

Désolé pour le titre vague, mais une partie de cette question est ce que ces deux styles de syntaxe sont appelés:F # correspondance explicite vs syntaxe de la fonction

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

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

L'autre partie est quelle différence il y a entre les deux, et quand Je voudrais utiliser l'un ou l'autre?

Répondre

40

La version de correspondance est appelée une "expression correspondant à motif". La version de la fonction est appelée "fonction de correspondance de modèle". Trouvé dans la section 6.6.4 du spec.

L'utilisation de l'un sur l'autre est une question de style. Je préfère n'utiliser la version de la fonction que lorsque j'ai besoin de définir une fonction qui n'est qu'une instruction de correspondance.

10

Ils font la même chose dans votre cas - les function agit par mot-clé comme une combinaison du mot-clé fun (pour produire un lambda anonyme) suivi par le mot-clé match.

Ainsi, techniquement ces deux sont les mêmes, avec l'ajout d'un fun:

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

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

N'est-ce pas en fait l'inverse - c'est-à-dire que 'fun' est techniquement défini en termes de' function | _ -> ... '? –

+1

Pour être précis, 'fun x y -> ...' serait 'fun x -> fun y -> ...', puis 'fun x -> ...' serait 'function | x -> ... '. C'est pourquoi vous pouvez faire correspondre les motifs dans 'fun' - par ex. 'fun (x :: xs) -> ...'. –

2

Les deux syntaxes sont équivalentes. La plupart des programmeurs choisissent l'un ou l'autre et l'utilisent ensuite systématiquement.

La première syntaxe reste plus lisible lorsque la fonction accepte plusieurs arguments avant de commencer à travailler.

59

Le pro pour la deuxième syntaxe est que lorsqu'il est utilisé dans un lambda, il pourrait être un peu plus laconique et facile à lire.

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

La version de fonction est un raccourci pour la syntaxe de correspondance complète dans le cas particulier où l'instruction de correspondance est la fonction entière et la fonction n'a qu'un seul argument (les tuples comptent comme un). Si vous voulez avoir deux arguments, vous devez utiliser la syntaxe de correspondance complète *. Vous pouvez le voir dans les types des deux fonctions suivantes. Comme vous pouvez le voir, la version de match prend deux arguments séparés alors que la version de la fonction prend un seul argument. J'utilise la version de la fonction pour la plupart des fonctions à un seul argument, car je trouve la syntaxe de la fonction plus propre.

* Si vous voulez vraiment vous pouvez obtenir la version de fonction pour la signature de type droit, mais il semble assez laid à mon avis - voir exemple ci-dessous.

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

Juste pour être complet, je viens à la page 321 de Expert FSharp:.

« Note, le Listing 12-2 utilise la forme d'expression function pattern-rules -> expression Cela équivaut à (fun x -> match x with pattern-rules -> expression) et est particulièrement pratique que un moyen de définir des fonctions fonctionnant directement sur des syndicats discriminés."

4

fonction permet seulement un argument, mais permet la correspondance de motif, tout en amusant est la façon plus générale et flexible pour définir une fonction Jetez un coup d'oeil ici. http://caml.inria.fr/pub/docs/manual-ocaml/expr.html

+0

pourquoi dites-vous seulement 1 argument au lieu de seulement le dernier argument? il est possible d'avoir plus d'un argument et d'utiliser "function". est-ce une interprétation de fonction d'ordre supérieur? – symbiont

0

C'est un vieille question, mais je vais jeter mon 0,02 $.

en général, j'aime mieux la version match puisque je viens du monde Python où « explicite est mieux que implicite. »

Bien sûr, si les informations de type sur le paramètre sont nécessaires, la version function ne peut pas être utilisée.

OTOH J'aime l'argument fait par Stringer donc je vais commencer à utiliser function en lambdas simples.