F # correspondance explicite vs syntaxe de fonction

Désolé pour le titre vague, mais une partie de cette question est ce que ces deux styles de syntaxe sont appelés:

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?

La version de correspondance est appelée “expression de correspondance de motif”. La version de fonction est appelée “fonction de correspondance de modèle”. Trouvé dans la section 6.6.4 de la spécification .

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

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

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

contre

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

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

 //val match_test : ssortingng -> ssortingng -> ssortingng let match_test xy = match x, y with | "A", _ -> "Hello A" | _, "B" -> "Hello B" | _ -> "Hello ??" //val function_test : ssortingng * ssortingng -> ssortingng let function_test = function | "A", _ -> "Hello A" | _, "B" -> "Hello B" | _ -> "Hello ??" 

Comme vous pouvez le constater, la version de la correspondance prend deux arguments distincts, tandis que la version de la fonction prend un seul argument en tuplé. J’utilise la version de fonction pour la plupart des fonctions à un seul argument car je trouve que la syntaxe de la fonction est plus propre.

* Si vous le voulez vraiment, vous pouvez obtenir la signature de type de la version de la fonction, mais à mon avis, elle est plutôt moche – voir l’exemple ci-dessous.

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

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

Donc techniquement, ces deux sont les mêmes, avec en plus un fun :

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

Juste par souci d’exhaustivité, je viens d’arriver à la page 321 d’ Expert FSharp :

“Le Listing 12-2 utilise l’expression form function pattern-rules -> expression . Ceci est équivalent à (fun x -> match x with pattern-rules -> expression) et est particulièrement pratique pour définir des fonctions fonctionnant directement sur les syndicats discriminés. ”

La fonction n’autorise qu’un seul argument mais permet la correspondance de motifs, tandis que le fun est la manière la plus générale et la plus souple de définir une fonction. Jetez un coup d’oeil ici: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html

Les deux syntaxes sont équivalentes. La plupart des programmeurs choisissent l’un ou l’autre et l’utilisent ensuite de manière cohérente.

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

C’est une vieille question mais je vais lancer mon $ 0.02.

En général, j’aime mieux la version de match puisque je viens du monde Python où “explicite est meilleur qu’implicite”.

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

OTOH J’aime l’argument de Ssortingnger , je vais donc commencer à utiliser la function dans les lambdas simples.