数据类型和匹配

Linked lists

和Perl一样,OCaml也将对列表的支持直接内建在语言中了。OCaml中一个列表的所有元素的类型必须一致。使用以下格式来写列表:

[1; 2; 3]

(注意是分号,不是逗号)。

[] 表示空列表。

一个列表有一个“”(第一个元素)和一个“”(剩下的元素)。头是一个元素,而尾则是一个列表,所以前面的例子中,表头是整数1,而表尾是list[2; 3]

另一种做法是使用cons操作符——头 :: 尾。所以下面的列表写法是完全一样的:

[1; 2; 3]
1 :: [2; 3]
1 :: 2 :: [3]
1 :: 2 :: 3 :: []

为什么我要提到cons操作符呢?其实,当我们对列表使用模式匹配的时候,它是相当有用的,下面我将详细说明。

链表的类型

整数链表的类型是int list,一般来说,foo类型的链表的类型就是foo list。

由此可以看出,链表的所有元素都必须是同一种类型的。但是类型却可以是多态的(如,'a list),当你要写操作"lists of anything"(任意类型的列表)的泛型函数时,这就相当有用了(注意,'a list 并不代表每个单独的元素可以有不同的类型——所以你还是不能用它来构造包含混合类型的列表,也就是说,元素的类型可以任意,但所有元素的类型必须相同)。

length函数是定义在OCaml的List模块中的,它是一个很好的例子。它不论列表包含的整数还是字符串或者对象、 还是什么小怪物,List.length函数都可以对其进行处理。因此,List.length的类型是:

List.length : 'a list -> int

Structures

C和C++都有作为structure简称的struct概念。尽管有点繁琐,Java中类也可以用于类似的效果。

考虑下面简单的C结构:

struct pair_of_ints {
  int a, b;
};

Ocaml中最简单的对应形式是一个组元(tuple),比如具有int * int类型的(3, 4)。和链表不同,组元的元素可以是不同类型,例如(3, "hello", 'x')的类型是int * string * char

在Ocaml中实现一个C中的struct还有另外一种稍显复杂的方法,就是使用记录。你可以像C的结构一样在记录中为元素命名。你不能在组元中命名元素,而是要记住它们出现的顺序。下面是和之前的C结构等价的一个记录:

type pair_of_ints = { a : int; b : int };;

它定义了记录的类型,然后构造一个该类型的对象:

{ a=3; b=5 }

请注意在类型定义中使用":",在构造对象时使用"="。

下面是在toplevel中输入一些例子的输出:

# type pair_of_ints = { a : int; b : int };;
type pair_of_ints = { a : int; b : int; }
# {a=3; b=5};;
- : pair_of_ints = {a = 3; b = 5}
# {a=3};;
Some record field labels are undefined: b

Ocaml要求结构中的所有元素都有确定的值。

Variants (qualified unions and enums)

TODO