9.1 改进以数据为中心的应用程序
我们回顾一下前面章节中讨论的以数据为中心的应用程序一些内容。第七章,我们讨论了以数据为中心的应用程序的关键是数据结构的设计。函数语言对数据结构的构造提供了非常简单、概念明确思考办法。我们已经学习了所有基本的数据类型,元组、差别联合和记录;还学习了声明泛型类型,实现了在不同程序中重用;讨论了 F# 库中的一些类型,如选项类型和函数式列表。
到目前为止,我们已经单独实现了数据类型的操作,这是函数式应用程序设计的通常方法,与面向对象程序设计不同,其中操作是类型声明的一部分。我们在第七章讨论过这一方法动机,但是,仍有必要简要回顾一下它对函数式程序的主要优势:
■ 在处理差别联合时,能够轻松地添加操作。
■在 F# 中,以这种方式写代码,语法非常简洁,因此,代码可以写得更快,而且能够很容易为不同的解决方案建立原型。
■能够充分利用 F# 的类型推理。正如我们在处理 .NET 对象时所看到的,由于编译器无法根据调用的成员推断出类型,因此,经常需要类型批注。
■这种编程风格也更好地支持了函数技术,比如散函数应用和管道。
■轻量级的函数式风格,可以使用 F# 交互式控制台(Interactive shell),轻松实现交互方式运行代码。
提示
如果操作能够保持独立于类型,数据结构就不会频繁更改。定义了数据结构以后,就可以创建这个类型的值了,并且能够一直存在于在 F# Interactive;然后,可以写函数的第一版,使用 F# Interactive 进行测试,改正可能出现的错误,对程序进行改进,并再次用同样的数据进行测试。如果我们对数据结构连同其所有的操作一起改变,这一过程将非常困难。
使操作成为数据结构的一部分,有许多理由支持,我们大部分经验可能来自 C#,我们用一个示例来说明。在第七章,我们写过一个简单的 Rect 类型,有两个处理函数。可以看到,清单 9.1 中重复了这段代码。示例使用了一些 System.Drawing 命名空间下的类型,因此,如果创建新项目,需要添加对 System.Drawing.dll 程序集的引用。
清单 9.1 Rect 类型和处理函数(F#)
open System.Drawing
type Rect =
{ Left: float32; Top: float32
Width: float32; Height:float32 }
let deflate(rc, wspace, hspace) = <-- 缩放矩形
{ Left = rc.Left + wspace; Width =rc.Width - (2.0f * wspace)
Top = rc.Top + hspace;Height = rc.Height - (2.0f * hspace) }
let toRectangleF(rc) = <-- 转换成 System.Drawing 表示
RectangleF(rc.Left, rc.Top,rc.Width, rc.Height)
首先,我们声明了类型,然后,定义两个操作处理矩形值。操作是用独立的 F# 函数实现的,但是,如果我们把它们实现为方法,在写代码时会更容易发现。在Visual Studio 中,不需要记住函数的名字,在值的名字后键入点,智能感知会弹出操作的列表;另外,代码也更好组织,因为我们知道类型中有哪些操作。如何从这两种方案F# 中选出最好的,很明显是一个难题。
原文地址:http://blog.csdn.net/hadstj/article/details/41824771