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
。