Coincidencia de patrón OCaml con no constantes

¿Es posible hacer coincidencias de patrones en variables en lugar de valores constantes?

# let x = 2 in
let y = 5 in
match 2 with
| x -> "foo"
| y -> "bar"
| _ -> "baz";;
            let y = 5 in
Warning 26: unused variable y.
  let x = 2 in
Warning 26: unused variable x.
  | y -> "bar"
Warning 11: this match case is unused.
  | _ -> "baz";;
Warning 11: this match case is unused.
- : string = "foo"

Obviamente, con esta sintaxis, el x -> "foo" caso se lleva todo. ¿Hay alguna manera de hacer que sea equivalente a:

match 2 with
| 2 -> "foo"
| 5 -> "bar"
| _ -> "baz"

donde los valores de las expresiones de coincidencia se determinan en tiempo de ejecución?

preguntado el 03 de mayo de 12 a las 17:05

3 Respuestas

A when guardia es una mala idea aquí en mi opinión. Los principiantes tienden a usar en exceso la sintaxis de coincidencia de patrones que encuentran conveniente, y esto da como resultado errores sutiles en su aplicación. Para una persona que notará que "oye, | y -> .. aquí no es lo que quiero", otras diez personas cometerán el error y no lo notarán directamente.

Debe desalentar ese patrón propenso a errores. Mi consejo personal para los principiantes es nunca utilizado when, Y a , solamente use la coincidencia de patrones para desestructurar los valores de un tipo de datos inductivo (como listas, árboles, opciones, etc.). La coincidencia de patrones en números enteros casi siempre es un error.

Recomiendo usar if ... then .. else if .. then .. else preferiblemente.

if z = x then "foo"
else if z = y then "bar"
else "baz"

¿Cuándo es legítimo usar when? Es comprensible tener uno cuando el resto de los casos sí se benefician del emparejamiento de patrones (para probar patrones anidados, etc.), o cuando la prueba se realiza sobre valores resultantes de una desestructuración profunda del valor emparejado. A menudo se puede traducir fusionando dos ramas y usando un if..then..else en la zona.

Un ejemplo en el que no es conveniente eliminarlo es el siguiente (ensayo combinado con desestructuración):

match foo with
| (Baz x) when pred x -> ...
| _ -> ... 

contestado el 04 de mayo de 12 a las 12:05

Necesita when Guardia:

let x = 2 in
let y = 5 in
match 2 with
| z when z = x -> "foo"
| z when z = y -> "bar"
| _ -> "baz";;

Los mensajes de error son muy instructivos. Cuando usas:

let x = 2 in
...
match 2 with
| x -> "foo"
| ...

el nuevo valor x ensombrece el valor x en let-bound anterior, de ahí el primer mensaje de error. Además, desde la nueva x coincide con todo, dos debajo de los patrones de y y _ son obviamente redundantes.

Tenga en cuenta que hacer coincidir una constante (match 2 with) no es una buena idea.

contestado el 03 de mayo de 12 a las 17:05

Sí, sé que la coincidencia constante no es una buena idea. Fue solo por el bien del ejemplo. - Nick Heiner

Creo que usando when guardias aquí es una mala idea, y tiende a fomentar el mal estilo entre los programadores (en particular, los principiantes). - Gasche

Un guardia de "cuándo" es lo que estás buscando aquí:

let x = 2 in
let y = 5 in
match 2 with
| x' when x' = x -> "foo"
| y' when y' = y -> "baz"
| _ -> "baz" ;;

... aunque no estoy seguro de por qué querrías hacer coincidir alguna vez con una constante.

contestado el 03 de mayo de 12 a las 18:05

La coincidencia con la constante fue solo por el bien del ejemplo. - Nick Heiner

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.