F # coincidencia explícita vs sintaxis de función

87

Lo siento por el título vago, pero parte de esta pregunta es cómo se llaman estos dos estilos de sintaxis:

let foo1 x = 
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one"

La otra parte es ¿qué diferencia hay entre los dos y cuándo querría usar uno u otro?

Benjol
fuente

Respuestas:

56

La versión de coincidencia se denomina "expresión de coincidencia de patrones". La versión de la función se denomina "función de coincidencia de patrones". Encontrado en la sección 6.6.4 de la especificación .

Usar uno sobre el otro es cuestión de estilo. Prefiero usar solo la versión de la función cuando necesito definir una función que es solo una declaración de coincidencia.

gradbot
fuente
Gracias. Aunque la programación funcional que usa F # dice que el uso de la palabra clave function indica que es una función de coincidencia de patrones, esta respuesta y el OP aclaran un momento de estancamiento cerebral.
octopusgrabbus
El vínculo parece estar roto.
MattMS
83

La ventaja de la segunda sintaxis es que cuando se usa en una lambda, podría ser un poco más concisa y legible.

List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1]

vs

List.map (function 1 -> "one" | _ -> "not one") [0;1;2;3;1]
Larguero
fuente
23

La versión de la función es una forma abreviada de la sintaxis de coincidencia completa en el caso especial en el que la declaración de coincidencia es la función completa y la función solo tiene un único argumento (las tuplas cuentan como uno). Si desea tener dos argumentos, debe usar la sintaxis de coincidencia completa *. Puede ver esto en los tipos de las siguientes dos funciones.

//val match_test : string -> string -> string
let match_test x y = match x, y with
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

//val function_test : string * string -> string                   
let function_test = function
                        | "A", _ -> "Hello A"
                        | _, "B" -> "Hello B"
                        | _ -> "Hello ??"

Como puede ver, la versión de coincidencia toma dos argumentos separados, mientras que la versión de la función toma un solo argumento tuplado. Utilizo la versión de la función para la mayoría de las funciones de un solo argumento ya que encuentro que la sintaxis de la función parece más limpia.

* Si realmente lo desea, puede obtener la versión de la función para que tenga el tipo de firma correcto, pero en mi opinión se ve bastante feo; vea el ejemplo a continuación.

//val function_match_equivalent : string -> string -> string
let function_match_equivalent x y = (x, y) |> function
                                                | "A", _ -> "Hello A"
                                                | _, "B" -> "Hello B"
                                                | _ -> "Hello ??"
Joshua
fuente
12

Hacen lo mismo en su caso: la functionpalabra clave actúa como una combinación de la funpalabra clave (para producir una lambda anónima) seguida de la matchpalabra clave.

Entonces, técnicamente, estos dos son iguales, con la adición de un fun:

let foo1 = fun x ->
    match x with
    | 1 -> "one"
    | _ -> "not one"

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"
Tim Robinson
fuente
1
¿No es realmente al revés, funes decir, técnicamente se define en términos de function | _ -> ...?
Pavel Minaev
1
Para ser específico, fun x y -> ...sería fun x -> fun y -> ..., y luego fun x -> ...sería function | x -> .... Es por eso que puede hacer coincidir patrones en fun, por ejemplo fun (x::xs) -> ....
Pavel Minaev
10

En aras de la integridad, acabo de llegar a la página 321 de Expert FSharp :

"Tenga en cuenta que el Listado 12-2 usa la forma de expresión function pattern-rules -> expression. Esto es equivalente (fun x -> match x with pattern-rules -> expression)y es especialmente conveniente como una forma de definir funciones que trabajan directamente sobre uniones discriminadas".

Benjol
fuente
6

La función solo permite un argumento pero permite la coincidencia de patrones, mientras que la diversión es la forma más general y flexible de definir una función. Eche un vistazo aquí: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html

kamaci
fuente
¿Por qué dice solo 1 argumento en lugar de solo el último argumento? es posible tener más de 1 argumento y usar "función". ¿Es esta una interpretación de función de orden superior?
symbiont
4

Las dos sintaxis son equivalentes. La mayoría de los programadores eligen uno u otro y luego lo usan de manera consistente.

La primera sintaxis permanece más legible cuando la función acepta varios argumentos antes de comenzar a trabajar.

Pascal Cuoq
fuente
2

Esta es una vieja pregunta, pero arrojaré mis $ 0.02.

En general me gusta más la matchversión ya que vengo del mundo Python donde "explícito es mejor que implícito".

Por supuesto, si se necesita información de tipo en el parámetro, functionno se puede utilizar la versión.

OTOH Me gusta el argumento de, Stringerasí que comenzaré a usarlo functionen lambdas simples.

Soldalma
fuente