2010-05-17 8 views
11

Dans « programmation F # » Je suis tombé sur un motif correspondant comme celui-ci (j'ai simplifié un peu):modèle Comprendre correspondant à l'opérateur de contre

let rec len list = 
    match list with 
    | [] -> 0 
    | [_] -> 1 
    | head :: tail -> 1 + len tail;; 

Pratiquement, je comprends que le dernier match reconnaît la tête et queue de la liste. Conceptuellement, je ne comprends pas pourquoi cela fonctionne. Pour autant que je comprenne, :: est l'opérateur contre, qui ajoute une valeur en tête de liste, mais il ne me semble pas qu'il soit utilisé comme opérateur ici. Dois-je comprendre cela comme une «syntaxe spéciale» pour les listes, où: est interprété comme un opérateur ou un «modèle de correspondance» selon le contexte? Ou peut-on étendre la même idée pour des types autres que des listes, avec d'autres opérateurs?

Répondre

10

En plus de la réponse de Brian, il y a quelques points à noter. La syntaxe h::t peut être utilisé à la fois comme un opérateur et comme motif:

let l = 1::2::[]     // As an operator 
match l with x::xs -> 1 | [] -> 0 // As a pattern 

Cela signifie qu'il est un peu construction spéciale, parce que d'autres opérateurs (par exemple +) ne peuvent pas être utilisés comme modèles (pour la décomposition le résultat revient aux arguments de l'opérateur) - évidemment, pour +, cela serait ambigu.

En outre, le motif [_] est intéressant car il s'agit d'un exemple de motif imbriqué. Il compose:

  • _ - motif de soulignement, ce qui correspond à une valeur quelconque et ne se lie pas de symboles
  • [ <pattern> ] - motif de liste d'élément unique, qui correspond à une liste avec des éléments simples et correspond à l'élément de la liste avec le <pattern> imbriqué.

Vous pouvez également écrire match 1::[] with | [x] -> x qui renvoie la valeur de l'élément unique (dans ce cas 1).

+0

Merci, votre remarque à propos de: être une construction spéciale est exactement ce que je n'étais pas clair. J'ai expérimenté en essayant d'utiliser d'autres opérateurs dans le pattern-matching de la même façon, mais ça n'avait pas beaucoup de sens et je n'ai rien trouvé, ce qui m'a fait me poser des questions sur les inconvénients. – Mathias

+1

Notez que la même chose est vraie pour Tuples - vous pouvez utiliser le motif (,) pour construire et pour faire correspondre/décompresser des tuples, et pour d'autres types aussi (Some()/None) etc – Benjol

+0

Voici une liste de [tous supportés types de modèles] (https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching) avec des exemples. – JanDotNet

13

Il s'agit d'une syntaxe spéciale pour les listes. Vous pouvez penser du type list comme une union de discrimination ainsi:

type list<'T> =   // ' 
    | Nil 
    | Cons of 'T * list<'T> 

sauf qu'il ya une syntaxe spéciale qui fait Nil être [] et Cons(h,t) être h::t. Ensuite, il s'agit simplement d'une correspondance de modèle normale sur une union discriminée. Est ce que ça aide?

(Eventuellement voir aussi this blog entry.)

+0

C'est très utile, merci! – Mathias

2

Il est utilisé comme un formateur ou formellement pattern, 'la liste » est adaptée aux trois modèles:

[] signifie que la liste est vide

[_] signifie que la liste a un élément, puisque vous ne vous souciez pas de ce que l'élément est, alors mettez simplement _ là, vous pouvez aussi utiliser [a]. Head :: tail signifie que la liste comporte deux parties: une tête et une queue.

Vous pouvez voir la correspondance de motif F # comme une structure puissante si sinon.

Questions connexes