F#显式匹配vs函数语法

Ben*_*jol 78 syntax f#

很抱歉这个模糊的标题,但这个问题的一部分是这两种语法样式的调用:

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

let foo2 = function 
    | 1 -> "one" 
    | _ -> "not one"
Run Code Online (Sandbox Code Playgroud)

另一部分是两者之间的区别,当我想要使用其中一个时?

Str*_*ger 72

第二种语法的专业版是,当在lambda中使用时,它可能更简洁和可读.

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

VS

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


gra*_*bot 51

匹配版本称为"模式匹配表达式".功能版本称为"模式匹配功能".见规范 6.6.4节.

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


Jos*_*hua 20

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

//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 ??"
Run Code Online (Sandbox Code Playgroud)

如您所见,匹配版本采用两个单独的参数,而函数版本采用单个tupled参数.我对大多数单个参数函数使用函数版本,因为我发现函数语法看起来更干净.

*如果你真的想要你可以获得功能版本以获得正确的类型签名但在我看来它看起来很丑 - 见下面的例子.

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


Tim*_*son 12

它们在您的情况下也做同样的事情 - function关键字的作用类似于fun关键字(生成匿名lambda)后跟match关键字的组合.

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

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

let foo2 = function
    | 1 -> "one"
    | _ -> "not one"
Run Code Online (Sandbox Code Playgroud)

  • 具体来说,“fun xy -> ...”将是“fun x -> fun y -> ...”,然后“fun x -> ...”将是“function |”。x -> ...`。这就是为什么你可以在 `fun` 中进行模式匹配 - 例如 `fun (x::xs) -> ...`。 (2认同)

Ben*_*jol 9

为了完整起见,我得到了Expert FSharp的第321页:

"注意,清单12-2使用表达式形式function pattern-rules -> expression.这相当于(fun x -> match x with pattern-rules -> expression)并且特别方便,可以定义直接在有区别的联合上工作的函数."


kam*_*aci 6

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