2008-10-14 13 views
47

He estado tratando de explicar la diferencia entre instrucciones de cambio y coincidencia de patrón (F #) a un par de personas pero realmente no he podido explicarlo bien ... la mayoría de las veces solo mírame y di "entonces, ¿por qué no solo usas si ... luego ... otra vez"?Explicando la coincidencia de patrones frente al interruptor

¿Cómo se las explicarías?

EDITAR! Gracias a todos por las excelentes respuestas, realmente me gustaría poder marcar múltiples respuestas correctas.

Respuesta

34

Habiendo sido anteriormente una de "esas personas", no sé si hay una forma concisa de resumir por qué la coincidencia de patrones es tan sabrosa. Es experiencial.

Cuando acababa de echar un vistazo a la coincidencia de patrones y pensé que era una declaración glorificada de cambio, creo que no tenía experiencia en programación con tipos de datos algebraicos (tuplas y uniones discriminadas) y no veía eso la coincidencia de patrones era tanto una construcción de control como una construcción de unión. Ahora que he estado programando con F #, finalmente "lo entiendo". La frialdad de la coincidencia de patrones se debe a la confluencia de las características que se encuentran en los lenguajes de programación funcionales, por lo que no es trivial para que el forastero pueda apreciarla.

Traté de resumir un aspecto de por qué la coincidencia de patrones es útil en la segunda de una corta serie de blog de dos partes sobre el lenguaje y el diseño de API; echa un vistazo a part one y part two.

+8

"experiencial". Buena palabra. :-) –

-1

¿Quizás podrías hacer una analogía con cadenas y expresiones regulares? Usted describe qué está buscando, y deja que el compilador descubra cómo por sí mismo. Hace que tu código sea mucho más simple y claro.

Como comentario adicional: encuentro que lo más útil sobre la coincidencia de patrones es que fomenta los buenos hábitos. Me ocupo de las cajas de esquina primeras, y es fácil comprobar que he cubierto todos los casos.

5

De la parte superior de mi cabeza:

  1. El compilador puede decir si usted no ha cubierto todas las posibilidades en sus partidos
  2. Puede utilizar un partido como una asignación
  3. Si usted tiene una unión discriminada, cada partido puede tener un "tipo" diferente
28

Los patrones le dan un lenguaje pequeño para describir la estructura de los valores que desea emparejar. La estructura puede ser arbitrariamente profunda y puede vincular variables a partes del valor estructurado.

Esto le permite escribir cosas muy sucintamente. Puede ilustrar esto con un pequeño ejemplo, como una función derivada de un tipo simple de expresiones matemáticas:

type expr = 
    | Int of int 
    | Var of string 
    | Add of expr * expr 
    | Mul of expr * expr;; 

let rec d(f, x) = 
    match f with 
    | Var y when x=y -> Int 1 
    | Int _ | Var _ -> Int 0 
    | Add(f, g) -> Add(d(f, x), d(g, x)) 
    | Mul(f, g) -> Add(Mul(f, d(g, x)), Mul(g, d(f, x)));; 

Además, debido a la coincidencia de patrones es una construcción estática para tipos estáticos, el compilador puede (i) verificar que cubrió todos los casos (ii) detectó ramas redundantes que nunca pueden igualar ningún valor (iii) proporcionan una implementación muy eficiente (con saltos, etc.).

+0

Buen ejemplo. Cuando explico la coincidencia de patrones con "personas no funcionales", me gustaría mencionar que con PM su condición puede verificar la "forma" de sus datos, lo que es mucho más difícil, feo e ineficiente con if/switch. –

+0

'Add of expr * expr' Creo que quisiste escribir' + ' –

+2

Sin lukas, esto es sintaxis abstracta, sin sintaxis concreta, entonces' + 'no es válido y' * 'no debe interpretarse como una multiplicación aritmética. 'Add of expr * expr' declara un constructor no constante' Add' cuyos 2 argumentos tienen el tipo 'expr'. Entonces lo usa para construir una combinación de 2 expresiones que está etiquetada como 'Agregar'. –

4

El interruptor es las dos ruedas delanteras.

El patrón de coincidencia es el automóvil completo.

+3

-1: El interruptor es solo una rueda. –

13

Extracto de this blog article:

patrón de juego tiene varias ventajas sobre los estados de conmutación y el envío método:

  • patrón coincide puede actuar sobre intercepciones, flotadores, cuerdas y otros tipos como así como objetos.
  • Las coincidencias de modelo pueden actuar sobre varios valores diferentes simultáneamente: coincidencia de patrones paralelos. El método de envío y cambio están limitados a un solo valor de , p. "esta".
  • Los patrones se pueden anidar, lo que permite el envío de sobre árboles de profundidad arbitraria. El envío y el cambio del método están limitados al en el caso no anidado.
  • Los patrones Or permiten que los subpatrones sean compartidos. El envío del método solo permite compartir cuando los métodos son de clases que comparten una clase base . De lo contrario, debe manualmente factorizar las características comunes en una función separada (dándole un nombre ) y luego insertar manualmente las llamadas desde todos los lugares apropiados a su función innecesaria .
  • La coincidencia de patrones proporciona la redundancia que detecta errores.
  • Las coincidencias anidadas y/o paralelas están optimizadas para usted por el compilador F #. El OO debe equivalente ser escrito a mano y en constante reoptimice con la mano durante desarrollo, que es prohibitivamente tedioso y propenso a errores, por lo que producción a la calidad del código OO tiende a ser extremadamente lento en comparación.
  • Los patrones activos le permiten inyectar la semántica de despacho personalizado .
3

Las coincidencias de patrón en OCaml, además de ser más expresivas como se menciona en varias formas que se han descrito anteriormente, también proporcionan algunas garantías estáticas muy importantes. El compilador demostrará para usted que el análisis de casos encarnada por su estado de patrón-partido es:

  • exhaustiva (ningún caso se pierden)
  • no redundantes (no hay casos que no pueden ser golpeados, ya que son se ha vaciado por un caso anterior)
  • de sonido (no hay patrones que son imposibles dado el tipo de datos en cuestión)

Este es un acuerdo muy grande. Es útil cuando escribe el programa por primera vez y es enormemente útil cuando su programa está evolucionando. Si se usa correctamente, las declaraciones de coincidencia hacen que sea más fácil cambiar los tipos en su código de manera confiable, porque el sistema de tipo le señala las declaraciones de coincidencia rotas, que son un indicador decente de dónde tiene que arreglar el código.

5

Tuplas tienen "," y las variantes tienen Ctor args ..estos son constructores, crean cosas.

Los patrones son destructores, los desgarran.

Son conceptos duales.

Para poner esto más enérgicamente: la noción de una tupla o variante no puede describirse simplemente por su constructor: se requiere el destructor o el valor que ha hecho es inútil. Son estas descripciones duales las que definen un valor.

Generalmente pensamos en constructores como datos y destructores como flujo de control. Los destructores variantes son ramas alternativas (una de muchas), los destructores de tuplas son hilos paralelos (todos muchos).

El paralelismo es evidente en operaciones como

(f * g) . (h * k) = (f . h * g . k) 

si se piensa en el control fluye a través de una función, tuplas proporcionan una manera de dividir un cálculo en hilos paralelos de control.

Visto de esta manera, las expresiones son formas de componer tuplas y variantes para crear estructuras de datos complicadas (piense en una AST).

Y las coincidencias de patrones son formas de componer los destructores (de nuevo, piense en un AST).

0

Las instrucciones If-Else (o switch) tratan acerca de elegir diferentes formas de procesar un valor (entrada) según propiedades del valor en cuestión.

La coincidencia de patrones se trata de definir cómo procesar un valor dada su estructura , (también tenga en cuenta que las coincidencias de patrón de un solo caso tienen sentido).

Por lo tanto, la coincidencia de patrones se trata más de deconstruir valores que tomar decisiones, esto los convierte en un mecanismo muy conveniente para definir funciones (recursivas) en estructuras inductivas (tipos de unión recursiva), lo que explica por qué se usan abundantemente en lenguajes como Ocaml etc.

PD: Puede conocer el patrón-partido y If-Else "patrones" de su uso ad-hoc en matemáticas;

"si x tiene la propiedad A continuación, y persona z"

(Si-Else) "algún plazo en p1..pn donde .... es la descomposición prima de x .." ((caso único) coincidencia de patrón)

Cuestiones relacionadas