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?

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.


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]

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

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"

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."


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


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.


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.