我已经看了O'Caml文档,但我仍然想知道,|
符号是什么意思或做什么?
这里有一个使用它的地方的例子:
(function (0, 0) -> "both zero"
| (0, _) -> "first only zero"
| (_, 0) -> "second only zero"
| (_, _) -> "neither zero")
但显然我不认为这包含了它的所有用途。
这是模式匹配(或者用更像数学的语言来说是" case analysis ")。OCaml的一个非常基本的特性。
ASCII符号|
用于分隔子句。它表示一种情况的析取,让人想起||
,它是布尔析取算子。
在这里,它与关键字function
一起使用,这意味着您构建一个闭包,该闭包可以立即与其参数(一对整数)进行模式匹配,而无需先命名它。
自定义和类型的定义遵循与模式匹配类似的语法。例子:
(* definition of a sum type
whose values are EITHER [None] OR [Some_int x]
where x is an integer: *)
type int_option =
| None
| Some_int of int
(* pattern matching on a value of type [int_option]: *)
let add (x_opt : int_option) (y : int) : int =
match x_opt with
| None -> y
| Some_int x -> x + y
在function
和match ... with
之后出现了一系列模式/表达式对。|
符号用于将这些对彼此分开。
在每对中,模式和表达式依次由->
分隔。
在模式中,|
可用于分离可选的子模式。
match x with
| (1 | 3 | 5 | 7) -> "odd"
| _ -> "even"
正如其他评论者指出的那样,|
也可以与其他字符组合成操作员名称。也就是说,OCaml名称(用于值)可以由特殊字符组成,如|
、>
、+
,如果您以正确的方式定义它们的话。(真正需要做的是在定义中把它们括起来。)
在OCaml中,|
用于分隔or模式中的大小写,或者用于分隔类型定义中的构造函数。OCaml中的模式无处不在,是该语言中最重要、最美丽的特性之一,它补充了另一个特性——代数数据类型。
代数数据类型被归纳地定义为一组形成规则。例如,我们可以为矩形、圆形、它们的组合或换位图形定义一个类型,例如
type figure =
| Rectangle of int * int
| Circle of int
| Composition of figure * figure
| Transposition of figure
上面的类型定义了可能图形的无限集。模式可以很容易地分析它们的结构。在没有模式的语言中,我们必须依赖于动态类型转换和if/then/else。
的确,你可以把模式看作是if/then/else分支工具的泛化,这在所有语言中都是通用的。在if/then/else中,我们正在解构布尔值,它只有两种情况,true
和false
。此外,true
和false
的值不包含任何附加信息。基本上,true
或false
的含义是由其名称定义的,没有其他含义。我们的图形示例是不同的,我们定义的每种情况都包含我们想要访问的额外信息,例如
let rec area f = match f with
| Rectangle (w,h) -> w * h
| Circle r -> 2*r*r + 2*r + 1
| Composition (l,r) -> area l + area r
| Transposition f -> area f
我们可以看到,我们的match
表达式就像一个三向if/then/else,它也将每个图形向下转换为其匹配的类型,并且可以轻松访问每个图形的属性,以便我们可以计算它们占用的象素数量。在缺乏模式匹配的语言中,我们将不得不依赖访问者模式来计算图形的面积。
我们还可以注意到,数据类型的定义是如何与模式匹配表达式一致的。实际上,如果定义声明了如何构造数据类型,那么模式匹配定义了如何解构数据类型。
另外,作为额外的跟踪,语法
let foo = function X -> a | Y -> b
是
的语法糖let foo v = match v with X -> a | Y -> b