我可以在没有警告的情况下解压缩F#列表吗?

时间:2017-03-05 20:09:26

标签: list f# pattern-matching

F#可以轻松解压元组。解包列表也是可行的,但编译器会发出警告:

let m = [1; 2; 3]
let [a; b; c] = m
// Incomplete pattern matches on this expression. For example, the value '[_;_;_;_]' may indicate a case not covered by the pattern(s)

有没有办法避免这种警告?

3 个答案:

答案 0 :(得分:5)

您可以使用#nowarn指令(在您的情况下为#nowarn "25")禁用每个文件的警告,也可以使用--nowarn在命令行上禁用警告。

查看F# Compiler Directives了解详情。

首次禁用时,目前无法再次重新启用警告。

如果无法将元素数量解压缩到[a;b;c],您的匹配可能会(意外地)导致运行时错误,因此您可以使用明确关于risc的完整匹配:

let m = [1;2;3]
let (a,b,c) =
    match m with
    | [a;b;c] -> (a,b,c)
    | _ -> failwith "Expected exactly three items in m"

答案 1 :(得分:4)

如果您的列表m包含2个或4个元素,会发生什么?

显然有一种方式,简单的旧模式匹配:

let a, b, c =
   match m with
   | [a;b;c] -> a,b,c 
   | _ -> ... // handle the length!=3 case

F#允许您在明确表示您只需要覆盖一个案例时解构右侧对象。这是元组的情况,因为只有一个元组类型可以匹配左侧和右侧。这样的东西显然不会编译,因为类型不匹配:

let m = 1, 2 

let a, b, c = m

然而,在您的情况下,并不能保证您在这种情况下实际上并不是这样:

let m = [ 1; 2 ]

let [1;2;3] = m

实际上,您要求编译器允许非详尽的模式匹配。您可以按照其他答案中的说明禁用警告,但是您可以通过这种方式调用运行时错误。

答案 2 :(得分:1)

一个显而易见但却不优雅的方式是:

let m = [1; 2; 3]
let a = List.item 0 m
let b = List.item 1 m
let c = List.item 2 m

您可以编写辅助函数以使其更整洁:

let unpack3 x = (List.item 0 x, List.item 1 x, List.item 2 x)

let (a, b, c) = unpack3 m

如果你知道你总是会有固定数量的物品,那么list基本上不合适。

相关问题