有时我使用这样的东西:
match foo a with
| 1 -> printfn "%s" (foo a)
| 0 -> printfn "ok"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我调用foo函数两次,如果它是昂贵的调用我使用此代码:
let tmp = foo a
match tmp with
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok"
Run Code Online (Sandbox Code Playgroud)
但在这种情况下,我创建了具有外部范围的变量(关于match表达式).
我正在寻找这样的东西:
match (foo a) as tmp with
| 1 -> printfn "%s" tmp
| 0 -> printfn "ok
Run Code Online (Sandbox Code Playgroud)
在这种情况下你用什么?有没有优雅的解决方案?
更新 - 真实的例子:
let collection = getValuesFromDatabase a
match Array.length collection with
| 0 -> printfn "nothing"
| _ -> bar collection.[0]
Run Code Online (Sandbox Code Playgroud)
let result =
let tmp = foo a
match tmp with
| 1 -> printfn "%d" tmp
| 0 -> printfn "ok"
Run Code Online (Sandbox Code Playgroud)
将整个事物嵌套在let-block 下不会污染命名空间tmp.语法有点重,但作为回报,它允许本地计算的任意复杂性.
或者,如果您的结果是a unit,则可以替换let为do:
do
let tmp = foo a
match tmp with
| 1 -> printfn "%d" tmp
| 0 -> printfn "ok"
Run Code Online (Sandbox Code Playgroud)
在模式匹配时,您可以一次匹配多个模式的值,将模式与&例如:
match [1;2;3] with
| (x::_)&(_::y::_) -> printfn "First element is %d, second element is %d" x y
Run Code Online (Sandbox Code Playgroud)
在这里,我使用两种模式匹配相同的列表:x::_和_::y::_.这个例子有点傻(我可能只是匹配x::y::_),但它传达了这个想法.
在您的示例中,您可以使用此机制通过将其与简单模式匹配来捕获整个值:
match foo a with
| 1&x -> printfn "%d" x
| 0 -> printfn "ok"
Run Code Online (Sandbox Code Playgroud)
这是为了响应您的编辑,您提供了一个"真实"示例,用于处理集合.
这个"真实"的例子实际上与你之前提供的"玩具"示例有所不同,你想要捕捉collection,但是你匹配Array.length collection- 不是同一件事.通常,除了将其置于如上所述的嵌套do或let块中之外,没有其他快捷方式.但在你的具体情况下,我可以像这样重写匹配:
match getValuesFromDatabase a with
| [||] -> printfn "nothing"
| xs -> bar xs.[0]
Run Code Online (Sandbox Code Playgroud)
在这里,Array.length我不是调用,而是将值与空数组匹配.这样,由于我匹配集合本身,我可以在第二个匹配的情况下捕获它并使用它来获取第一个元素.
如果您想执行比空数组检查更复杂的检查,您还可以使用模式保护:
match getValuesFromDatabase a with
| xs when Array.length xs = 0 -> printfn "nothing"
| xs -> bar xs.[0]
Run Code Online (Sandbox Code Playgroud)