2011-04-11 15 views
5

varsayalım Aşağıdaki kod var:Eksik desen eşlemesini filtre olarak kullanmak mı?

type Vehicle = 
| Car of string * int 
| Bike of string 

let xs = [ Car("family", 8); Bike("racing"); Car("sports", 2); Bike("chopper") ] 

ben gibi döngü için bir zorunluluk eksik desen eşleştirme kullanarak listenin üzerindeki filtreleyebilirsiniz:

> for Car(kind, _) in xs do 
> printfn "found %s" kind;; 

found family 
found sports 
val it : unit =() 

ama bir neden olur: warning FS0025: Incomplete pattern matches on this expression. For example, the value 'Bike (_)' may indicate a case not covered by the pattern(s). Unmatched elements will be ignored.

Eşsiz öğelerin göz ardı edilmesi niyetim olduğu için, bu uyarıdan kurtulmak için bir olasılık var mı?

Ve bu çalışmayı bir MatchFailureException oluşturmadan liste-anlamalarıyla yapmanın bir yolu var mı? Örneğin. Böyle bir şey:

> [for Car(_, seats) in xs -> seats] |> List.sum;; 
val it : int = 10 
+0

Bence bu hat şu şekilde olurdu: [xs -> koltuklar] 'da Bus (_, koltuklar) için |> List.sum ;; Sağ? ;) –

+0

Oh anladım! 2 araba! 5 x 2 = 10! Tanrım, yardım et bana. –

+0

Bu bir aile arabası ve spor araba, yani 8 + 2 = 10. – Laurent

cevap

10

İki yıl önce, senin kod geçerli olduğunu ve bunu yapmak için standart bir yol oldu: Sizin kodları aşağıdaki gibi bir daha idomatic şekilde yazılmış olabilir. Daha sonra, dil temizlendi ve tasarım kararı açık sözdizimini desteklemekti. Bu nedenle, uyarıyı görmezden gelmenin iyi bir fikir olmadığını düşünüyorum.

Kodunuzdaki için standart yerine geçer:

for x in xs do 
    match x with 
    | Car(kind, _) -> printfn "found %s" kind 
    | _ ->() 

, List.sumBy iyi uyabilecek başka biri için

(ayrıca yüksek mertebeden fonksiyonlarının pedi numunede sahiptir kullanabilirsiniz):

0:
xs |> List.sumBy (function Car(_, seats) -> seats | _ -> 0) 

Eğer comprehensions kalmayı tercih ederse, bu açık sözdizimi

+0

İlginç. Bahsettiğiniz "temizlik" i tanımlayan bir referans/bağlantınız var mı ve bu değişikliğin gerekçesini tartışıyor musunuz? – gasche

+4

@gasche: Bilgisayarımda eski derleyiciler var, size 1.9.3.14 ve 1.9.6.16 sürümleri arasında gerçekleşen değişimi söyleyebilirim. Bunun için uygun bir başvuru bulamıyorum, ancak bu sürüm notları bir sözdizimi sadeleştirmesinden söz eder: [link] (http: //blogs.msdn.com/b/dsyme/arşiv/2008/08/29/ayrıntılı salınımlı-notlar-için f-Eylül-2008-ctp-release.aspx). Burada ayrıca bir tartışma var: [link] (http://cs.hubfs.net/forums/thread/12072.aspx). – Laurent

+1

Örüntüler karmaşık olabileceğinden (veya aktif kalıplar olarak tanımlanabileceğinden), okuyucunun bir döngü olup olmadığı her zaman açık değildir. Sanırım bu bir gerekçe olabilir (şahsen ben bu sözdizimini çok beğendim). Ayrıca, hesaplama ifadelerindeki döngülerin nasıl desugared olduğunu görüyorsanız, bir MatchFailureException öğesini geliştirdiği açıktır. – Laurent

5

Sen üzerinden herhangi uyarıyı engelleyebilirsiniz #nowarn direktif veya --nowarn: derleyici seçeneği (FS0025 burada 25 olarak, uyarı sayısını geçmesi).

Fakat daha genel olarak, hayır, en iyi şey diğer cevapta olduğu gibi (örneğin choose ile) açıkça filtrelemektir.

+1

Bu uyarıyı yerel olarak devre dışı bırakma olasılığının olduğunu umuyorum. Bir Öznitelik kullanarak. Ama yine de teşekkürler! :) –

5

Eşsiz durumları görmezden gelmek istediğinizi açıkça belirtmek için List.choose'u kullanabilir ve bu benzersiz öğeler için None'u kullanabilirsiniz.

let _ = xs |> List.choose (function | Car(kind, _) -> Some kind 
            | _ -> None) 
      |> List.iter (printfn "found %s") 

let sum = xs |> List.choose (function | Car(_, seats)-> Some seats 
             | _ -> None) 
      |> List.sum 
+5

Bunu daha da özlü hale getirebilirsiniz: xs |> List.choose (işlev Araba (tür, _) -> Bazı (tür) | _ -> Yok) ' –

+0

teşekkür ederim. Cevabınız da çok yardımcı oldu (ve sizinki ile Laurent arasında karar vermek zordu). –

İlgili konular