这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」
Records(记录)
OCaml中的记录很像其他语言中的结构体。下面举个例子,
utop # type ptype = TNormal | TFire | TWater;;
type ptype = TNormal | TFire | TWater
utop # type mon = { name : string; hp : int; ptype : ptype };;
type mon = { name : string; hp : int; ptype : ptype; }
复制代码
我们可以看到定义了一个叫做mon
的记录,包含三个字段:name
、hp
和ptype
。并且这些字段的类型都已经确定了。这里有一个点是,ptype
不仅是类型名称也是字段名称。
我们可以创建一个mon
类型的变量,并且访问其中的字段
utop # let c = { name = "Charmander"; hp = 39; ptype = TFire };;
val c : mon = {name = "Charmander"; hp = 39; ptype = TFire}
utop # c.hp;;
- : int = 39
复制代码
也可以用模式匹配来访问记录的字段
utop # match c with { name = n; hp = h; ptype = t} -> h;;
- : int = 39
复制代码
其中,n
,h
和t
是模式变量。这里有一个语法糖: 如果你想匹配的变量名称和字段的名称相同,可以进行简写:
utop # match c with { name ; hp ; ptype } -> hp;;
- : int = 39
复制代码
Syntax
记录的语法形式上为
{ f1 = e1; ...; fn = en }
复制代码
其中,一个字段访问可以写成
e.f
复制代码
其中f
为字段的名称,而不是一个表达式。
这里动态和静态的语义就不过多介绍。
Tuples
和记录一样,元组也是一种组合的数据结构。与记录中需要给字段命名不同的是,元组通过位置来决定。下面有几个元组的例子:
(1, 2, 10)
(true, "Hello")
([1; 2; 3], (0.5, 'X'))
复制代码
元组中只有两个元素为一个匹配(pair
)。有三个元素的被称为tripe
。
超过三个元素的,通常使用记录而不是元组,因为当字段过长记住每个字段所代表的含义会很麻烦。
也可以通过模式匹配来访问元组:
utop # match (1, 2, 3) with (x, y, z) -> x + y + z;;
- : int = 6
复制代码
Variants vs. Tuples and Records
下面说一下 变种与元组和记录的区别
The big difference between variants and the types we just learned (records and tuples) is that a value of a variant type is one of a set of possibilities, whereas a value of a tuple or record type provides each of a set of possibilities. Going back to our examples, a value of type
day
is one ofSun
orMon
or etc. But a value of typemon
provides each of astring
and anint
andptype
. Note how, in those previous two sentences, the word “or” is associated with variant types, and the word “and” is associated with tuple and record types. That’s a good clue if you’re ever trying to decide whether you want to use a variant, or a tuple or record: if you need one piece of data or another, you want a variant; if you need one piece of data and another, you want a tuple or record.
One-of types are more commonly known as sum types, and each-of types as product types. Those names come from set theory. Variants are like disjoint union, because each value of a variant comes from one of many underlying sets (and thus far each of those sets is just a single constructor hence has cardinality one). Disjoint union is indeed sometimes written with a summation operator ΣΣ. Tuples/records are like Cartesian product, because each value of a tuple or record contains a value from each of many underlying sets. Cartesian product is usually written with a product operator, ×× or ΠΠ.