模式与列表变量匹配

时间:2018-10-29 14:14:07

标签: f#

为什么第二个模式匹配返回“ 1和2”并在通配符_上警告我“此规则将永远不会匹配”?

let a = [3;4]

match a with
    |[1;2] -> "1 and 2"
    |_ -> "Other"
|> printfn "%A"

let lst = [1;2]
match a with
    |lst -> "1 and 2"
    |_ -> "Other"
|> printfn "%A"

在我看来,这首先是事实。怎么这样?

2 个答案:

答案 0 :(得分:3)

小写的标识符与所有内容匹配,并将标识符绑定到值。

如果要将lsta进行比较,则需要使用when,它是有条件的保护措施:

let a = [3;4]

match a with
    |[1;2] -> "1 and 2"
    |_ -> "Other"
|> printfn "%A"

let lst = [1;2]
match a with
    | b when b = lst -> "1 and 2"
    |_ -> "Other"
|> printfn "%A"

,但在这种情况下,简单的if then else就可以了。

答案 1 :(得分:1)

在第二个模式匹配中,您有两个具有相同名称的不同lst变量。在这里,

let lst = [1;2]
match a with
    | lst -> "1 and 2"
    | _ -> "Other"

在第一种匹配情况下,您没有引用上面的lst变量,则创建了一个新变量。您可以通过尝试对其进行重构-重命名(在Visual Studio中为F2)进行检查。正如AMieres解释的那样,案例很重要。

通常,在区分大小写的情况下引用变量是可行的,但并非易事。 考虑以下代码:

let helloWorld = "hello world"

let isHelloWorld s =
    match s with
    | helloWorld -> true
    | _ -> false

在这里您将得到与上述相同的警告。一种可行的方法是用[<Literal>]属性标记常量,并同时使其变为大写:

[<Literal>]
let HelloWorld = "hello world"

let isHelloWorld s =
    match s with
    | HelloWorld -> true
    | _ -> false

这将按预期工作。但是,您只能将[<Literal>]属性应用于certain types,并且列表不在其中。对于这些,您必须在匹配情况下利用when条件。