2010-05-17 10 views
11

En "Programación F #" me encontré con un patrón de coincidencia como éste (he simplificado un poco):entendimiento de coincidencia de patrones con el operador contras

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

Prácticamente, entiendo que el último partido reconoce la cabeza y cola de la lista. Conceptualmente, no entiendo por qué funciona. Por lo que entiendo, :: es el operador contras, que añade un valor en la posición de la cabeza de una lista, pero no me parece que se esté utilizando como operador aquí. ¿Debería entender esto como una "sintaxis especial" para las listas, donde :: se interpreta como un operador o un "patrón de coincidencia" según el contexto? ¿O se puede extender la misma idea para otros tipos de listas, con otros operadores?

Respuesta

10

Además de la respuesta de Brian, hay algunos puntos que vale la pena señalar. La sintaxis h::t puede ser utilizado tanto como un operador y como un patrón:

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

Esto significa que se trata de una construcción especial de bits, debido a que otros operadores (por ejemplo +) no se pueden utilizar como patrones (para descomponer el resultado vuelve a los argumentos del operador) - obviamente, para +, esto sería ambiguo.

Además, el patrón [_] es interesante, porque es un ejemplo de patrón anidado. Se compone:

  • _ - Destacar patrón, que coincide con cualquier valor y no se une ningún símbolos
  • [ <pattern> ] - de un solo elemento de lista de patrones, que coincide con un listas con elementos individuales y coincide con el elemento de la lista con el <pattern> anidado.

También podría escribir match 1::[] with | [x] -> x que devolvería el valor del elemento individual (en este caso 1).

+0

Gracias, tu punto acerca de :: ser una construcción especial es exactamente lo que no estaba claro. Experimenté intentando usar otros operadores en la coincidencia de patrones de la "misma" manera, pero no tenía mucho sentido y no llegué a ninguna parte, que es lo que me hizo preguntarme sobre las desventajas. – Mathias

+1

Tenga en cuenta que lo mismo es cierto para Tuples: puede usar el patrón (,) para compilar y combinar/desempaquetar tuplas, y para otros tipos también (Some()/None) etc. – Benjol

+0

Aquí hay una lista de [all supported tipos de patrones] (https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/pattern-matching) con ejemplos. – JanDotNet

13

Es una sintaxis especial para las listas. Se puede pensar en el tipo list como una unión discriminado así:

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

excepto que hay una sintaxis especial que hace que sea Nil[] y Cons(h,t) ser h::t. Entonces es solo una coincidencia de patrón normal en una unión discriminada. ¿Eso ayuda?

(Posiblemente véase también this blog entry.)

+0

¡Es muy útil, gracias! – Mathias

2

Se utiliza como un formateador o formalmente pattern, se corresponde `lista' a los tres patrones:

[] significa la lista está vacía

[_] significa que la lista tiene un elemento, ya que no le importa cuál es el elemento, simplemente ponga _ allí, también puede usar [a].

head :: tail significa que la lista tiene dos partes: una cabeza y una cola.

Puede ver la coincidencia de patrón F # como una poderosa estructura if else else.

Cuestiones relacionadas