F # corrispondenza esplicita vs sintassi della funzione


87

Mi dispiace per il titolo vago, ma parte di questa domanda è come vengono chiamati questi due stili di sintassi:

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

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

L'altra parte è che differenza c'è tra i due e quando vorrei usare l'uno o l'altro?

Risposte:


56

La versione match è chiamata "espressione di pattern matching". La versione della funzione è chiamata "funzione di corrispondenza dei modelli". Si trova nella sezione 6.6.4 delle specifiche .

Usare l'uno sull'altro è una questione di stile. Preferisco usare solo la versione della funzione quando ho bisogno di definire una funzione che è solo un'istruzione match.


Grazie. Sebbene la programmazione funzionale con F # dica che l'uso della parola chiave function indica che si tratta di una funzione di pattern matching, questa risposta e l'OP chiariscono un momento di blocco del cervello.
octopusgrabbus

Il collegamento sembra essere interrotto.
MattMS

83

Il vantaggio della seconda sintassi è che, se usata in un lambda, potrebbe essere un po 'più concisa e leggibile.

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]

23

La versione della funzione è una scorciatoia per la sintassi della corrispondenza completa nel caso speciale in cui l'istruzione match è l'intera funzione e la funzione ha solo un singolo argomento (le tuple contano come uno). Se vuoi avere due argomenti, devi usare la sintassi di corrispondenza completa *. Puoi vederlo nei tipi delle seguenti due funzioni.

//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 ??"

Come puoi vedere, match version accetta due argomenti separati mentre la funzione version accetta un singolo argomento tuplicato. Uso la versione della funzione per la maggior parte delle funzioni con argomento singolo poiché trovo che la sintassi della funzione sia più pulita.

* Se davvero lo desideri, puoi ottenere la versione della funzione per avere la firma del tipo giusto, ma a mio parere sembra piuttosto brutta - vedi l'esempio sotto.

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

12

Fanno la stessa cosa nel tuo caso: la functionparola chiave si comporta come una combinazione della funparola chiave (per produrre un lambda anonimo) seguita dalla matchparola chiave.

Quindi tecnicamente questi due sono gli stessi, con l'aggiunta di un fun:

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

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

1
Non è effettivamente il contrario - cioè funè tecnicamente definito in termini di function | _ -> ...?
Pavel Minaev

1
Per essere precisi, fun x y -> ...sarebbe fun x -> fun y -> ..., e quindi fun x -> ...sarebbe function | x -> .... È per questo che puoi eseguire la corrispondenza dei modelli in fun- ad es fun (x::xs) -> ....
Pavel Minaev

10

Per completezza, sono appena arrivato alla pagina 321 di Expert FSharp :

"Nota, il Listato 12-2 utilizza la forma dell'espressione function pattern-rules -> expression. Ciò è equivalente (fun x -> match x with pattern-rules -> expression)ed è particolarmente conveniente come un modo per definire le funzioni che lavorano direttamente su unioni discriminate."


6

la funzione consente solo un argomento ma consente la corrispondenza di modelli, mentre il divertimento è il modo più generale e flessibile per definire una funzione. Dai un'occhiata qui: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html


perché dici solo 1 argomento invece dell'ultimo argomento? è possibile avere più di 1 argomento e utilizzare "funzione". è questa un'interpretazione della funzione di ordine superiore?
simbionte

4

Le due sintassi sono equivalenti. La maggior parte dei programmatori sceglie l'uno o l'altro e quindi lo utilizza in modo coerente.

La prima sintassi rimane più leggibile quando la funzione accetta diversi argomenti prima di iniziare a lavorare.


2

Questa è una vecchia domanda, ma butto i miei $ 0,02.

In generale mi piace di più la matchversione poiché provengo dal mondo Python dove "esplicito è meglio che implicito".

Ovviamente se sono necessarie informazioni sul tipo sul parametro, la functionversione non può essere utilizzata.

OTOH Mi piace l'argomento fatto da Stringerquindi inizierò a usarlo functionin semplici espressioni lambda.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.