F # açık eşleme ve işlev sözdizimi


90

Belirsiz başlık için üzgünüz, ancak bu sorunun bir kısmı bu iki söz dizimi stilinin adıdır:

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

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

Diğer kısım, ikisi arasında ne fark olduğu ve birini ne zaman kullanmak isteyeceğim?

Yanıtlar:


58

Eşleşme versiyonuna "model eşleştirme ifadesi" adı verilir. İşlev sürümüne "desen eşleştirme işlevi" adı verilir. Spesifikasyonun 6.6.4 bölümünde bulundu .

Birini diğerinin üzerinde kullanmak bir stil meselesidir. Yalnızca bir eşleşme ifadesi olan bir işlevi tanımlamam gerektiğinde yalnızca işlev sürümünü kullanmayı tercih ederim.


Teşekkür ederim. İşlevsel Programlama F # kullanarak işlev anahtar sözcüğünün kullanımının bunun bir örüntü eşleştirme işlevi olduğunu gösterdiğini söylese de, bu yanıt ve OP, beyin sıkışmış bir anı açıklığa kavuşturur.
octopusgrabbus

Bağlantı kopmuş görünüyor.
MattMS

84

İkinci sözdiziminin uzmanı, bir lambda'da kullanıldığında biraz daha kısa ve okunaklı olabileceğidir.

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

Eşleşme ifadesinin tüm işlev olduğu ve işlevin yalnızca tek bir argümana sahip olduğu (tuplelar bir olarak sayılır) özel durumda işlev sürümü, tam eşleşme sözdizimi için kısa bir eldir. İki bağımsız değişkene sahip olmak istiyorsanız, tam eşleşme sözdizimini * kullanmanız gerekir. Bunu aşağıdaki iki işlevin türlerinde görebilirsiniz.

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

Gördüğünüz gibi, eşleşme sürümü iki ayrı argüman alırken, fonksiyon versiyonu tek bir tupled argüman alır. İşlev sözdiziminin daha temiz göründüğünü bulduğum için çoğu tek bağımsız değişken işlevi için işlev sürümünü kullanıyorum.

* Eğer gerçekten istiyorsanız, işlev sürümünün doğru tip imzasına sahip olmasını sağlayabilirsiniz, ancak bence oldukça çirkin görünüyor - aşağıdaki örneğe bakın.

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

12

Sizin durumunuzda da aynı şeyi yaparlar - functionanahtar kelime, funanahtar kelimenin (anonim bir lambda üretmek için) ardından anahtar kelimenin bir kombinasyonu gibi davranır match.

Yani teknik olarak bu ikisi aynı, a eklenmiş fun:

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

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

1
Aslında tam tersi değil mi - yani funteknik olarak açısından tanımlanıyor function | _ -> ...mu?
Pavel Minaev

1
Spesifik olmak gerekirse, fun x y -> ...olur fun x -> fun y -> ...ve sonra fun x -> ...olur function | x -> .... Bu yüzden içinde desen eşleştirme yapabilirsiniz fun- örneğin fun (x::xs) -> ....
Pavel Minaev

10

Eksiksizlik uğruna, Uzman FSharp'ın 321. sayfasına gittim :

"Not, Liste 12-2, ifade biçimini kullanır function pattern-rules -> expression. Bu, (fun x -> match x with pattern-rules -> expression)doğrudan ayrımcılığa uğramış sendikalar üzerinde çalışan işlevleri tanımlamanın bir yolu olarak eşdeğerdir ve özellikle uygundur."


6

işlevi yalnızca bir argümana izin verir, ancak desen eşleştirmesine izin verirken, eğlence bir işlevi tanımlamanın daha genel ve esnek yoludur. Buraya bir göz atın: http://caml.inria.fr/pub/docs/manual-ocaml/expr.html


neden sadece son argüman yerine sadece 1 argüman söylüyorsunuz? 1'den fazla argümana sahip olmak ve "function" kullanmak mümkündür. bu daha yüksek dereceli bir fonksiyon yorumu mu?
symbiont

4

İki sözdizimi eşdeğerdir. Çoğu programcı birini veya diğerini seçer ve ardından tutarlı bir şekilde kullanır.

İlk sözdizimi, işlev çalışmaya başlamadan önce birkaç bağımsız değişkeni kabul ettiğinde daha okunaklı kalır.


2

Bu eski bir soru ama 0,02 dolarımı atacağım.

Genel matcholarak, "açık olanın örtükten daha iyi olduğu" Python dünyasından geldiğim için sürümü daha çok seviyorum .

Elbette, parametrede tür bilgisi gerekiyorsa functionsürüm kullanılamaz.

OTOH tarafından yapılan argümanı beğendim, Stringerböylece functionbasit lambdalarda kullanmaya başlayacağım .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.