Correspondência explícita F # vs sintaxe da função

87

Desculpe pelo título vago, mas parte desta questão é como esses dois estilos de sintaxe são chamados:

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

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

A outra parte é que diferença existe entre os dois e quando eu gostaria de usar um ou outro?

Benjol
fonte

Respostas:

56

A versão de correspondência é chamada de "expressão de correspondência de padrão". A versão da função é chamada de "função de correspondência de padrões". Encontrado na seção 6.6.4 da especificação .

Usar um sobre o outro é uma questão de estilo. Prefiro usar apenas a versão de função quando preciso definir uma função que seja apenas uma instrução de correspondência.

gradbot
fonte
Obrigado. Embora a Programação Funcional com F # diga que o uso da palavra-chave function indica que é uma função de correspondência de padrões, esta resposta e o OP esclarecem um momento de bloqueio cerebral.
octopusgrabbus
O link parece estar quebrado.
MattMS
83

A vantagem da segunda sintaxe é que, quando usada em um lambda, pode ser um pouco mais concisa e legível.

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]
Longarina
fonte
23

A versão da função é uma abreviação para a sintaxe de correspondência completa no caso especial em que a instrução de correspondência é a função inteira e a função tem apenas um único argumento (as tuplas contam como um). Se você quiser ter dois argumentos, precisará usar a sintaxe de correspondência completa *. Você pode ver isso nos tipos das duas funções a seguir.

//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 você pode ver, a versão de correspondência leva dois argumentos separados, enquanto a versão da função usa um único argumento tuplado. Eu uso a versão de função para a maioria das funções de argumento único, pois acho que a sintaxe da função parece mais limpa.

* Se você realmente quiser, pode obter a versão da função para ter o tipo de assinatura correto, mas parece muito feio na minha opinião - veja o exemplo abaixo.

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

Eles fazem a mesma coisa no seu caso - a functionpalavra - chave atua como uma combinação da funpalavra - chave (para produzir um lambda anônimo) seguida pelomatch palavra chave.

Então, tecnicamente, esses dois são iguais, com a adição de um fun:

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

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"
Tim Robinson
fonte
1
Não é realmente o contrário - isto funé, é tecnicamente definido em termos de function | _ -> ...?
Pavel Minaev
1
Para ser específico, fun x y -> ...seria fun x -> fun y -> ..., e então fun x -> ...seria function | x -> .... É por isso que você pode fazer correspondência de padrões em fun- por exemplo fun (x::xs) -> ....
Pavel Minaev
10

Apenas para completar, acabei de acessar a página 321 do Expert FSharp :

"Observe, a Listagem 12-2 usa a forma de expressão function pattern-rules -> expression. Isso é equivalente (fun x -> match x with pattern-rules -> expression)e especialmente conveniente como uma maneira de definir funções que trabalham diretamente em uniões discriminadas."

Benjol
fonte
6

function permite apenas um argumento, mas permite a correspondência de padrões, enquanto fun é a maneira mais geral e flexível de definir uma função. Dê uma olhada aqui: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html

Kamaci
fonte
por que você diz apenas 1 argumento em vez de apenas o último argumento? é possível ter mais de 1 argumento e usar "função". esta é uma interpretação de função de ordem superior?
simbionte
4

As duas sintaxes são equivalentes. A maioria dos programadores escolhe um ou outro e usa-o de forma consistente.

A primeira sintaxe permanece mais legível quando a função aceita vários argumentos antes de começar a trabalhar.

Pascal Cuoq
fonte
2

Esta é uma pergunta antiga, mas vou jogar meus $ 0,02.

Em geral eu gosto mais do match versão, já que venho do mundo Python, onde "explícito é melhor do que implícito".

Claro, se a informação de tipo no parâmetro for necessária, o function versão não pode ser usada.

OTOH Eu gosto do argumento feito por, Stringerentão vou começar a usar functionem lambdas simples.

Soldalma
fonte