7.1.1 使用 F# 记录类型

时间:2022-02-22 19:08:14

7.1.1 使用 F# 记录类型

 

记录是“有标记元组(labeledtuples)”,是把几个不同的元素保存在一个值中;此外,每个元素都有一个可以用来访问的名字。在 F# 中,元素的名字叫字段(fields),它在很多方面类似于 C 的记录或结构(struct)构造,或者 C# 中的匿名类型。记录与匿名类型既有不同,即必须事先声明,也有相同,在基本形式中,记录只包含唯一属性,保存数据;清单 7.1 显示了表示矩形的声明。

 

清单 7.1 使用记录类型表示矩形 (F# Interactive)

 

> type Rect =

     { Left : float32     | 声明记录的字段

       Top :float32      |

       Width: float32    |

       Height: float32 };; |

type Rect = (...)

 

> let rc = { Left = 10.0f; Top = 10.0f;  | [1]

Width = 100.0f; Height = 200.0f; };;   |

val rc : Rect = (...)    [2]

 

> rc.Left + rc.Width;;    <-- 通过名字访问字段

val it : float32 = 110.0f

 

声明记录类型,必须指定字段的类型和名字。在这个示例中,我们使用 float32 类型,它对应于 C# 中的 float 和 .NET 的 System.Single 类型,在后面,我们会用到这个类型的矩形。创建 F# 记录的值,在大括号中指定所有字段的值[1]。注意,因为能够通过字段的名字自动推断,所以,不必写出记录类型名字,在示例中可以看到,编译器正确地推断出我们所创建值的类型为 Rect。这一点与 C# 中匿名类型是不同的,如果编译器按照字段的名字,找不到任何适当的记录类型,将会报错。

使用记录时,不权需要读字段,而且需要更改字段的值,比如,向右移动矩形。由于记录是函数式数据结构,是不可变的,因此,必须用改变后的值创建[新的]记录。向右移动的矩形记录,写出来可能像这样:

 

let rc2 = { Left = rc.Left + 100.0f; Top =rc.Top;

               Width = rc.Width; Height = rc.Height }

 

如果都要这样写代码,就太笨拙了。因为,必须显式复制保存在记录中的所有字段值;另外,还可能需要在记录声明中增加新字段,可能完全打乱现有的代码,所以,F# 提供了简洁的方式来表达“复制现有的记录,并作部分修改”的思想:

 

let rc2 = { rc with Left = rc.Left + 100.0f}

 

使用 with 关键字,指定要更改的字段值,而其余的所有字段会自动复制。与前面的代码具有同样的功能,但更实用。

至此,我们已经知道写记录的“基本”操作,那么,如何以函数风格写代码,真正实现用函数操作记录呢。