Ale*_*sti 5 f# list-comprehension pattern-matching
假设我有以下代码:
type Vehicle =
| Car of string * int
| Bike of string
let xs = [ Car("family", 8); Bike("racing"); Car("sports", 2); Bike("chopper") ]
Run Code Online (Sandbox Code Playgroud)
我可以使用不完整的模式匹配过滤上面的列表,如下所示:
> for Car(kind, _) in xs do
> printfn "found %s" kind;;
found family
found sports
val it : unit = ()
Run Code Online (Sandbox Code Playgroud)
但它会导致: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
Run Code Online (Sandbox Code Playgroud)
Lau*_*ent 10
两年前,您的代码是有效的,这是标准的方法.然后,语言已被清理,设计决策是支持显式语法.出于这个原因,我认为忽略警告并不是一个好主意.
代码的标准替换是:
for x in xs do
match x with
| Car(kind, _) -> printfn "found %s" kind
| _ -> ()
Run Code Online (Sandbox Code Playgroud)
(你也可以在pad样本中使用高阶函数)
对于另一个,List.sumBy很适合:
xs |> List.sumBy (function Car(_, seats) -> seats | _ -> 0)
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢坚持理解,这是明确的语法:
[for x in xs do
match x with
| Car(_, seats) -> yield seats
| _ -> ()
] |> List.sum
Run Code Online (Sandbox Code Playgroud)
您可以通过#nowarn指令或--nowarn:编译器选项使任何警告静音(传递警告编号,此处25如下FS0025).
但更一般地说,不,最好的事情就是明确过滤,就像在另一个答案中一样(例如choose).
要明确声明要忽略不匹配的大小写,可以使用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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1843 次 |
| 最近记录: |