F#显式匹配与函数语法

对于模糊的标题感到抱歉,但这个问题的一部分是这两种语法风格被称为:

let foo1 x = match x with | 1 -> "one" | _ -> "not one" let foo2 = function | 1 -> "one" | _ -> "not one" 

另一部分是两者之间有什么区别,什么时候我想要使用其中之一?

匹配版本被称为“模式匹配expression式”。 function版本被称为“模式匹配function”。 在规范的第6.6.4节中find。

使用一个在另一个是一个风格的问题。 当我需要定义一个只是匹配语句的函数时,我更喜欢只使用函数版本。

对于第二种语法的专家来说,在lambda中使用时,可能会更简洁和可读。

 List.map (fun x -> match x with | 1 -> "one" | _ -> "not one") [0;1;2;3;1] 

VS

 List.map (function 1 -> "one" | _ -> "not one") [0;1;2;3;1] 

在匹配语句是整个函数并且函数只有一个参数(元组计数为1)的特殊情况下,函数版本是完整匹配语法的简写。 如果你想有两个参数,那么你需要使用完全匹配的语法*。 你可以在下面两个函数的types中看到这个。

 //val match_test : string -> string -> string let match_test xy = match x, y with | "A", _ -> "Hello A" | _, "B" -> "Hello B" | _ -> "Hello ??" //val function_test : string * string -> string let function_test = function | "A", _ -> "Hello A" | _, "B" -> "Hello B" | _ -> "Hello ??" 

正如你所看到的,匹配版本需要两个独立的参数,而函数版本只需要一个元组参数。 我使用大多数单参数函数的函数版本,因为我发现函数语法看起来更干净。

*如果你真的想要你可以得到function版本有正确的types签名,但在我看来,它看起来很丑陋 – 见下面的例子。

 //val function_match_equivalent : string -> string -> string let function_match_equivalent xy = (x, y) |> function | "A", _ -> "Hello A" | _, "B" -> "Hello B" | _ -> "Hello ??" 

他们在你的情况下做同样的事情 – function关键字行为就像fun关键字(产生一个匿名lambda)和match关键字的组合。

所以在技术上这两个是相同的,增加了一个fun

 let foo1 = fun x -> match x with | 1 -> "one" | _ -> "not one" let foo2 = function | 1 -> "one" | _ -> "not one" 

为了完整起见,我刚到专家FSharp的 321页:

“注意,程序清单12-2使用expression式expression式function pattern-rules -> expression ,这相当于(fun x -> match x with pattern-rules -> expression) ,作为定义直接工作的函数超过歧视的工会“。

函数只允许一个参数,但允许模式匹配,而fun是定义一个函数的更一般和更灵活的方式。 看看这里: http : //caml.inria.fr/pub/docs/manual-ocaml/expr.html

这两个语法是等价的。 大多数程序员select一个或另一个,然后一致地使用它。

当函数在开始工作之前接受几个参数时,第一个语法保持更好的可读性。

这是一个古老的问题,但我会抛出0.02美元。

一般来说,我喜欢更好的match版本,因为我来自Python世界,其中“显式优于隐式”。

当然,如果需要参数的types信息,则不能使用function版本。

OTOH我喜欢Stringer提出的论点,所以我将开始在简单的lambda中使用function