2011-04-11 25 views
5

Supongamos que tengo el siguiente código:¿Usar coincidencia de patrón incompleta como filtro?

type Vehicle = 
| Car of string * int 
| Bike of string 

let xs = [ Car("family", 8); Bike("racing"); Car("sports", 2); Bike("chopper") ] 

I puede filtrar por encima de lista mediante la coincidencia de patrones incompleta en un imperativo para bucle como:

> for Car(kind, _) in xs do 
> printfn "found %s" kind;; 

found family 
found sports 
val it : unit =() 

pero causará un: warning FS0025: Incomplete pattern matches on this expression. For example, the value 'Bike (_)' may indicate a case not covered by the pattern(s). Unmatched elements will be ignored.

Como el ignorar elementos incomparables es mi intención, ¿hay alguna posibilidad de deshacerse de esta advertencia?

¿Y hay una manera de hacer que esto funcione con listas de comprensión sin causar una excepción MatchFailureException? p.ej. algo así:

> [for Car(_, seats) in xs -> seats] |> List.sum;; 
val it : int = 10 
+0

Creo que esa línea se suponía que era: [para Bus (_, asientos) en xs -> asientos] |> List.sum ;; ¿Derecha? ;) –

+0

¡Oh lo entiendo! 2 autos! 5 x 2 = 10! Señor ayudame. –

+0

Es un automóvil familiar y deportivo, por lo que 8 + 2 = 10. – Laurent

Respuesta

10

dos años, su código es válido y que fue la forma estándar de hacerlo. Luego, el lenguaje se ha limpiado y la decisión de diseño fue favorecer la sintaxis explícita. Por esta razón, creo que no es una buena idea ignorar la advertencia.

La sustitución estándar para el código es:

for x in xs do 
    match x with 
    | Car(kind, _) -> printfn "found %s" kind 
    | _ ->() 

(también se puede utilizar funciones de alto orden tiene en la muestra de la almohadilla)

Por el otro, List.sumBy encajaría bien:

xs |> List.sumBy (function Car(_, seats) -> seats | _ -> 0) 

Si prefiere seguir con comprensiones, esta es la sintaxis explícita:

[for x in xs do 
    match x with 
    | Car(_, seats) -> yield seats 
    | _ ->() 
] |> List.sum 
+0

Interesante. ¿Tiene una referencia/enlace que describe la "limpieza" que mencionó, y discute la justificación de este cambio? – gasche

+4

@gasche: Tengo compiladores antiguos en mi computadora, puedo decirles que el cambio ocurrió entre las versiones 1.9.3.14 y 1.9.6.16. No puedo encontrar una referencia adecuada para esto, pero esas notas de la versión mencionan una simplificación de sintaxis: [link] (http: //blogs.msdn.com/b/dsyme/archive/2008/08/29/detailed-release-notes-for-the-f-september-2008-ctp-release.aspx). También hay una discusión aquí: [link] (http://cs.hubfs.net/forums/thread/12072.aspx). – Laurent

+1

Como los patrones pueden ser complejos (o definidos como patrones activos), no siempre estuvo claro para el lector si un ciclo se estaba filtrando o no. Supongo que esto podría ser una justificación (personalmente, disfruté esta sintaxis). Además, cuando ve cómo se desean los bucles en las expresiones de cálculo, está claro que está generando una excepción MatchFailureException. – Laurent

5

Se puede silenciar ninguna advertencia a través de la directiva o #nowarn--nowarn: opción del compilador (pasar el número de advertencia, aquí como en 25FS0025).

Pero, en general, no, lo mejor es filtrar explícitamente, como en la otra respuesta (por ejemplo, con choose).

+1

Esperé que hubiera una posibilidad de desactivar esta advertencia localmente, p. mediante el uso de un atributo. ¡Pero gracias de todos modos! :) –

5

Para indicar explícitamente que desea ignorar casos no coincidentes, puede usar List.choose y devolver None para esos elementos no coincidentes. Sus códigos se podrían escribir de una manera más idiomáticas de la siguiente manera: hace

let _ = xs |> List.choose (function | Car(kind, _) -> Some kind 
            | _ -> None) 
      |> List.iter (printfn "found %s") 

let sum = xs |> List.choose (function | Car(_, seats)-> Some seats 
             | _ -> None) 
      |> List.sum 
+5

Puede hacer que esto sea más conciso como 'xs |> List.choose (función Car (kind, _) -> Some (kind) | _ -> None)' –

+0

gracias. su respuesta también fue muy útil (y difícil de decidir entre la suya y la de Laurent). –

Cuestiones relacionadas