您收到该错误的原因是当您在匹配表达式的模式子句中使用变量名时 F# 正在做什么。
假设我有
match arg with
| x when x = 0 -> "zero"
| y when y = 1 -> "one"
| _ -> "other"
我认为这里的关键是要注意,尽管在比赛之前没有定义 x 或 y,但这段代码仍然可以工作。这是因为 x 和 y 只是使编写匹配表达式更容易的短代码。在幕后,F# 编译器实际上将其x when x = 0
转换x
为绑定到arg
. x
然后可以在x = 0
表达式和 . 之后的表达式中使用->
。
回到你遇到的问题:
let key1 = 1
let key2 = 2
let value =
match arg with
| key1 -> "value1"
| key2 -> "value2"
| _ -> failwith "key not found"
这不起作用的原因是因为在匹配表达式中,F# 重新绑定key1
到 的值arg
,所以key1 -> "value1" is equivalent to
如果 arg1 = arg1 则为“value1”。第一个模式将始终匹配;所以,key2
永远_
也达不到。
我不确定我的解释有多清楚,所以我也会用第二种方法来解释发生了什么:
如果将匹配表达式转换为 if-else,它将如下所示:
let key1 = 1
let key2 = 2
let value =
if let key1 = arg in arg = key1 then
"value1"
else if let key2 = arg in arg = key2 then
"value2"
else
failwith "key not found"
(为什么是的,F# 将允许您将 let 绑定放入 if 表达式中)
此 if/else 表达式等同于您的匹配表达式。在这种形式中,很明显第一个条件将始终评估为真。
这里就不放了,但是看一下匹配表达式的代码引用可能会有所帮助。直到我看到它们生成的抽象语法树是什么样子的,我才真正了解匹配表达式发生了什么。