F# 在'match'表达式中寻找类似'let'的东西

F# 在'match'表达式中寻找类似'let'的东西,f#,F#,有时我会用这样的方式: match foo a with | 1 -> printfn "%s" (foo a) | 0 -> printfn "ok" match (foo a) as tmp with | 1 -> printfn "%s" tmp | 0 -> printfn "ok match getValuesFromDatabase a with | [||] -> printfn "nothing" | xs -> bar xs.[0]

有时我会用这样的方式:

match foo a with
| 1 -> printfn "%s" (foo a)
| 0 -> printfn "ok"
match (foo a) as tmp with
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok
match getValuesFromDatabase a with 
| [||] -> printfn "nothing"
| xs -> bar xs.[0]
在这种情况下,我调用foo函数两次,如果调用代价很高,我将使用以下代码:

let tmp = foo a
match tmp with 
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok"
但在本例中,我创建了一个外部作用域为match表达式的变量

我在找这样的东西:

match foo a with
| 1 -> printfn "%s" (foo a)
| 0 -> printfn "ok"
match (foo a) as tmp with
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok
match getValuesFromDatabase a with 
| [||] -> printfn "nothing"
| xs -> bar xs.[0]
在这种情况下你用什么?有什么优雅的解决方案吗

更新-真实示例:

let collection = getValuesFromDatabase a
match Array.length collection with 
| 0 -> printfn "nothing"
| _ -> bar collection.[0]
选项1:使用let-or-do块 将整个内容嵌套在let块下可以防止tmp污染名称空间。语法有点重,但反过来它允许本地计算的任意复杂性

或者,如果您的结果是一个单位,您可以将let替换为do:

选项2:使用模式别名 模式匹配时,您可以一次将一个值与多个模式匹配,将模式与&分开,例如:

在这里,我用两种模式匹配同一个列表:x::u和::y:u。这个例子有点傻,我本可以用x::y::匹配,但它传达了这个想法

在您的示例中,您可以使用此机制通过将其与普通模式匹配来捕获整个值:

 match foo a with
 | 1&x -> printfn "%d" x
 | 0 -> printfn "ok"
更新:真实的例子 这是对您的编辑的回应,您在编辑中提供了一个真实的示例,该示例处理一个集合

这个真实的示例实际上不同于您之前提供的玩具示例,因为您希望捕获集合,但您在Array.length集合上进行了匹配-这不是同一件事。一般来说,除了如上所述将其放入嵌套的do或let块之外,没有快捷方式。但在你的特殊情况下,我可以这样改写比赛:

match foo a with
| 1 -> printfn "%s" (foo a)
| 0 -> printfn "ok"
match (foo a) as tmp with
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok
match getValuesFromDatabase a with 
| [||] -> printfn "nothing"
| xs -> bar xs.[0]
在这里,我没有调用Array.length,而是将值与空数组匹配。这样,因为我正在匹配集合本身,所以我可以在第二个匹配案例中捕获它,并使用它获取第一个元素

如果要执行比空数组检查更复杂的检查,还可以使用模式保护:

match getValuesFromDatabase a with 
| xs when Array.length xs = 0 -> printfn "nothing"
| xs -> bar xs.[0]

在您的实际示例中,您可以使用if。在任何复杂的数据类型上,您都不是真正的模式匹配,而这正是匹配的亮点所在。如果要测试集合是否为空,可以编写如下内容:

let collection = getValuesFromDatabase a
if Array.length collection = 0 then printfn "nothing"
else bar collection.[0]

也许我过于简单化了,但是你知道fooa产生了一个常数1,为什么不直接打印呢?@JeffMercado,我添加了更现实的示例。如果您关心范围,为什么不将该代码包装到函数中,让调用方返回新函数的结果?调用它的是一个变量模式:如果long ident是一个不以大写字符开头的单个标识符,它将被解释为一个变量模式。在检查过程中,变量被赋予与模式输入相同的值和类型。在我的问题的更新部分,是否有任何方法可以将模式别名应用到实际示例中?