F#显式匹配vs函数语法


87

抱歉,标题模糊,但这部分问题是这两种语法样式分别是什么:

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

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one"

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

Answers:


55

匹配版本称为“模式匹配表达式”。该功能版本称为“模式匹配功能”。在规范的6.6.4节中找到。

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


谢谢。尽管使用F#进行函数式编程表示使用function关键字表明它是一种模式匹配函数,但此答案和OP可以澄清大脑停滞的时刻。
octopusgrabbus

链接似乎已断开。
MattMS

82

第二种语法的优点是,在lambda中使用时,它可能更简洁易读。

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

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

23

在特殊情况下,函数版本是完全匹配语法的简写形式,在特殊情况下,match语句是整个函数,并且该函数仅具有单个参数(元组计为一个)。如果要有两个参数,则需要使用完全匹配语法*。您可以在以下两个功能的类型中看到它。

//val match_test : string -> string -> string
let match_test x y = 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 ??"

如您所见,匹配版本采用两个单独的参数,而函数版本采用单个元组参数。我将函数版本用于大多数单参数函数,因为我发现函数语法看起来更简洁。

*如果您确实想要,可以使函数版本具有正确的类型签名,但是在我看来,它看起来很丑陋-请参见下面的示例。

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

12

在您的情况下,它们执行相同的操作-function关键字的行为类似于fun关键字(产生匿名lambda)和match关键字的组合。

因此,从技术上讲,这两个是相同的,只是增加了一个fun

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

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"

1
难道不是实际上相反吗?也就是说fun,从技术上讲,是用function | _ -> ...
帕维尔·米纳夫

1
具体来说,fun x y -> ...将是fun x -> fun y -> ...,然后fun x -> ...将是function | x -> ...。这就是为什么你可以在做模式匹配fun-如fun (x::xs) -> ...
帕维尔·米纳夫

10

出于完整性考虑,我仅进入Expert FSharp的321页:

“请注意,清单12-2使用表达式形式function pattern-rules -> expression。这等效于(fun x -> match x with pattern-rules -> expression)并且特别方便,因为它是定义直接在可区分的并集上工作的函数的方式。”



4

这两种语法是等效的。大多数程序员选择一个或另一个,然后持续使用它。

当函数在开始工作之前接受多个参数时,第一种语法仍然更具可读性。


2

这是一个老问题,但是我会丢掉我的0.02美元。

总的来说,我更喜欢该match版本,因为我来自Python世界,“显性要比隐性好”。

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

OTOH我喜欢的说法,Stringer因此我将开始function在简单的lambda中使用它。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.