F # pencocokan eksplisit vs sintaks fungsi

90

Maaf tentang judul yang tidak jelas, tetapi bagian dari pertanyaan ini adalah apa nama kedua gaya sintaks ini:

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

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

Bagian lainnya adalah apa perbedaan antara keduanya, dan kapan saya ingin menggunakan salah satunya?

Benjol
sumber

Jawaban:

58

Versi yang cocok disebut "ekspresi pencocokan pola". Versi fungsi disebut "fungsi pencocokan pola". Ditemukan di bagian 6.6.4 dari spesifikasi .

Menggunakan salah satu dari yang lain adalah masalah gaya. Saya lebih suka hanya menggunakan versi fungsi ketika saya perlu mendefinisikan fungsi yang hanya pernyataan kecocokan.

gradbot
sumber
Terima kasih. Meskipun Pemrograman Fungsional Menggunakan F # mengatakan penggunaan kata kunci fungsi menunjukkan itu adalah fungsi pencocokan pola, jawaban ini dan OP mengklarifikasi momen brain stuck.
octopusgrabbus
Tautan tampaknya rusak.
MattMS
84

Pro untuk sintaks kedua adalah ketika digunakan dalam lambda, itu bisa sedikit lebih singkat dan mudah dibaca.

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]
Stringer
sumber
23

Versi fungsi adalah kependekan dari sintaks pencocokan penuh dalam kasus khusus di mana pernyataan kecocokan adalah keseluruhan fungsi dan fungsi hanya memiliki satu argumen (tupel dihitung sebagai satu). Jika Anda ingin memiliki dua argumen, maka Anda perlu menggunakan sintaks pencocokan penuh *. Anda dapat melihat ini dalam tipe dari dua fungsi berikut.

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

Seperti yang Anda lihat, versi pencocokan membutuhkan dua argumen terpisah sedangkan versi fungsi menggunakan satu argumen tuple. Saya menggunakan versi fungsi untuk sebagian besar fungsi argumen karena saya menemukan sintaks fungsi terlihat lebih bersih.

* Jika Anda benar-benar ingin, Anda bisa mendapatkan versi fungsi untuk memiliki tanda tangan tipe yang tepat tetapi menurut saya tampilannya cukup jelek - lihat contoh di bawah.

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

Mereka melakukan hal yang sama dalam kasus Anda - functionkata kunci bertindak seperti kombinasi funkata kunci (untuk menghasilkan lambda anonim) diikuti dengan matchkata kunci.

Jadi secara teknis keduanya sama, dengan tambahan a fun:

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

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"
Tim Robinson
sumber
1
Bukankah sebenarnya sebaliknya - yaitu funsecara teknis didefinisikan dalam istilah function | _ -> ...?
Pavel Minaev
1
Untuk lebih spesifik, fun x y -> ...akan menjadi fun x -> fun y -> ..., dan kemudian fun x -> ...akan function | x -> .... Itu sebabnya Anda dapat melakukan pencocokan pola di fun- mis fun (x::xs) -> ....
Pavel Minaev
10

Demi kelengkapan, saya baru saja sampai ke halaman 321 dari Expert FSharp :

"Catatan, Daftar 12-2 menggunakan bentuk ekspresi function pattern-rules -> expression. Ini setara dengan (fun x -> match x with pattern-rules -> expression)dan sangat nyaman sebagai cara untuk mendefinisikan fungsi yang bekerja secara langsung di atas serikat yang terdiskriminasi."

Benjol
sumber
6

function hanya memungkinkan untuk satu argumen tetapi memungkinkan untuk pencocokan pola, sedangkan fun adalah cara yang lebih umum dan fleksibel untuk mendefinisikan suatu fungsi. Lihat di sini: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html

kamaci
sumber
mengapa Anda mengatakan hanya 1 argumen, bukan hanya argumen terakhir? mungkin memiliki lebih dari 1 argumen dan menggunakan "fungsi". apakah ini interpretasi fungsi orde tinggi?
symbiont
4

Kedua sintaks itu setara. Kebanyakan programmer memilih satu atau yang lain dan kemudian menggunakannya secara konsisten.

Sintaks pertama tetap lebih mudah dibaca saat fungsi menerima beberapa argumen sebelum mulai bekerja.

Pascal Cuoq
sumber
2

Ini adalah pertanyaan lama tapi saya akan membuang $ 0,02 saya.

Secara umum saya lebih suka matchversinya karena saya berasal dari dunia Python di mana "eksplisit lebih baik daripada implisit."

Tentu saja jika informasi tipe pada parameter diperlukan, functionversi tersebut tidak dapat digunakan.

OTOH Saya suka argumen yang dibuat oleh Stringerjadi saya akan mulai menggunakan functionlambda sederhana.

Soldalma
sumber