对于模糊的标题感到抱歉,但这个问题的一部分是这两种语法样式的名称:
let foo1 x =
match x with
| 1 -> "one"
| _ -> "not one"
let foo2 = function
| 1 -> "one"
| _ -> "not one"
另一部分是两者之间的区别,当我想要使用其中一个时?
答案 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.";
。