F#显式匹配vs函数语法

时间:2009-12-03 10:23:46

标签: syntax f#

对于模糊的标题感到抱歉,但这个问题的一部分是这两种语法样式的名称:

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

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

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

8 个答案:

答案 0 :(得分:68)

第二种语法的专业版是,当在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 :(得分:49)

匹配版本称为“模式匹配表达式”。功能版本称为“模式匹配功能”。见spec的第6.6.4节。

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

答案 2 :(得分:17)

在特殊情况下,函数版本是完全匹配语法的简写,其中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 ??"

正如您所看到的,匹配版本采用两个单独的参数,而函数版本采用单个tupled参数。我对大多数单个参数函数使用函数版本,因为我发现函数语法看起来更清晰。

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

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

答案 3 :(得分:12)

他们在您的情况下执行相同操作 - function关键字的作用类似于fun关键字(生成匿名lambda)后跟match关键字的组合。 / p>

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

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

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

答案 4 :(得分:8)

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

  

“注意,清单12-2使用表达式function pattern-rules -> expression。这相当于(fun x -> match x with pattern-rules -> expression),并且作为一种定义直接在受歧视联合上工作的函数的方式特别方便。”

答案 5 :(得分:6)

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

答案 6 :(得分:4)

这两种语法是等价的。大多数程序员选择其中一个,然后一致地使用它。

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

答案 7 :(得分:1)

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

总的来说,我更喜欢function版本,因为我来自Python世界,其中"显式优于隐式。"

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

OTOH我喜欢function所提出的论点,所以我将开始在简单的lambdas中使用function fullDeleteFolder($dir) { echo "Remove: ".$dir."<br>"; if (is_dir($dir)) { $objects = scandir($dir); foreach ($objects as $object) { if ($object != "." && $object != "..") { if (is_dir($dir."/".$object)){ fullDeleteFolder($dir."/".$object); }else{ unlink($dir."/".$object); } } } rmdir($dir); } } $location = "[some-location]/mpcache/mod_pagespeed"; fullDeleteFolder($location); //might also want to do this for the 'media/css_secure' folder too, if your site is on https echo "Finished.";