给出基本记录
type t = {a:string;b:string;c:string}
为什么这段代码会编译
let f t = match t with
{a;b;_} -> a
但是这个
let f t = match t with
{_;b;c} -> b
和
let f t = match t with
{a;_;c} -> c
没有?我出于好奇而问这个明显无用的代码示例。
答案 0 :(得分:7)
可选的_
字段必须是最后一个字段。这被记录为Section 7.2
以下是参考资料:
pattern ::= ...
∣ '{' field ['=' pattern] { ';' field ['=' pattern] } [';' '_' ] [';'] '}'
答案 1 :(得分:5)
因为后两个例子在语法上是不正确的。语法允许您使用下划线终止字段名称模式,以通知编译器您已经知道,有多个字段比您尝试匹配的字段多。它用于抑制警告(默认情况下禁用)。以下是OCaml manual对此的说法:
可选地,记录模式可以通过以下方式终止: _表示记录模式中并未列出记录类型的所有字段并且它是故意的。默认情况下,编译器会忽略; _注释。如果打开警告9,编译器将在记录模式未能列出相应记录类型的所有字段且未终止时发出警告; _。继续上面的点例子,
如果要匹配名称而不将其绑定到变量,则应使用以下语法:
{a=_; b; c}
如,
let {a=_; b; c} = {a="hello"; c="cruel"; b="world"};;
val b : string = world
val c : string = cruel
答案 2 :(得分:2)
为了增加Jeffrey Scofield和ivg的答案,实际上可以通过使用不同的字段顺序来实现错误的例子。像这样:
let f t = match t with
{b;c;_} -> b