2011-04-11 39 views
5

假設我有以下代碼:使用不完整的模式匹配作爲過濾器?

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

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

我可以使用不完整的圖案匹配過濾器上方列表中的當務之急樣環:

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

found family 
found sports 
val it : unit =() 

,但它會引起: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.

由於忽視無與倫比的元素是我的意圖,是否有可能擺脫這種警告?

有沒有辦法使這項工作與列表理解而不會導致MatchFailureException?例如類似的東西:

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

我認爲這條線假設是:[公共汽車(_,座位)在xs - >席位] |> List.sum ;;對? ;) – 2011-04-11 23:52:01

+0

哦,我明白了! 2輛車! 5 x 2 = 10!主啊,幫助我。 – 2011-04-12 00:03:27

+0

這是一輛家庭轎車和一輛跑車,所以8 + 2 = 10。 – Laurent 2011-04-12 00:05:27

回答

10

兩年前,您的代碼是有效的,而且它是執行此操作的標準方法。然後,語言已經被清理,設計決定是傾向於顯式語法。出於這個原因,我認爲忽略警告並不是一個好主意。

爲您的代碼標準的更換:

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

(你也可以使用高階函數有墊樣品中)

對於其他一,List.sumBy會合身:

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

如果您更願意堅持內涵,這是明確的語法:

[for x in xs do 
    match x with 
    | Car(_, seats) -> yield seats 
    | _ ->() 
] |> List.sum 
+0

有趣。你是否有參考/鏈接來描述你提到的「清理」,並討論這種改變的合理性? – gasche 2011-04-12 09:00:27

+4

@gasche:我的電腦上有舊的編譯器,我可以告訴你1.9.3.14和1.9.6.16版本之間發生了變化。我無法找到適當的參考,但這些發行說明提到了語法簡化:[link](http://blogs.msdn。COM/B/dsyme /存檔/ 2008/8月29日/詳細釋放小筆記換了-F-月-2008-CTP-release.aspx)。這裏還有一個討論:[link](http://cs.hubfs.net/forums/thread/12072.aspx)。 – Laurent 2011-04-12 09:42:02

+1

由於模式可能很複雜(或定義爲活動模式),因此讀者並不總是清楚循環是否過濾。我想這可能是一個理由(我個人喜歡這種語法)。另外,當你看到計算表達式中的循環如何被清除時,很明顯它會引發MatchFailureException異常。 – Laurent 2011-04-12 09:53:46

5

您可以通過沉默任何警告#nowarn指令或--nowarn:編譯器選項(通過警告編號,這裏25FS0025)。

但是更一般地說,不,最好的辦法是明確地過濾,就像在其他答案中一樣(例如使用choose)。

+1

我希望有可能在本地禁用此警告,例如:通過使用一個屬性。但是,謝謝! :) – 2011-04-12 08:41:25

5

要明確指出您希望忽略不匹配的情況,可以使用List.choose並返回None表示那些不匹配的元素。您的代碼可以採用更具代表性的方式編寫,如下所示:

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

你可以使這個更簡潔,像'xs |> List.choose(函數Car(kind,_) - > Some(kind)| _ - > None)' – 2011-04-11 23:06:21

+0

謝謝。你的回答也很有幫助(很難在你和Laurent之間做出決定)。 – 2011-04-12 08:40:02