2011-04-11 58 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