15.1.3 可组合值

来源:互联网 发布:数控锥度螺纹编程实例 编辑:程序博客网 时间:2024/06/01 09:20

15.1.3 可组合值

 

    把问题描述为值,是把"语言"嵌入 F# 中的最简单的方法。这仅适用于简单的问题:我们不要指定任何复杂行为(比如,过滤函数的断言) ,和只需要通过组合基元对象或集合,并指定它们的属性,就能描述的大多数的问题。

    当代码有效地描述值时,我们可以在 F# 中实现它,通过创建类型,能够创建指定所有属性的值。表示这类问题的最常见的 F# 类型,是差别联合,对于有大量属性的基元,也可以使用列表(表示项的集合),或记录。清单 15.1 显示一个简单的类型声明,与前面 LISP 中示例同样的动画。

 

Listing 15.1 Specifying animations using discriminated unions (F#)

 

type AnimatedLocation =
  | Static of PointF
  | Rotating of PointF * float32
  | Linear of PointF * PointF

type Animation =
  | Disc of Brush * int * AnimatedLocation
  | Compose of Animation * Animation

 

    使用这个类型,我们现在可以创建描述简单动画的值。从某种意义上讲,清单 15.1 中的类型指定的语法,也用于创建动画的库,因为它指定了什么是有效的动画值。下面的代码片断显示在 LISP 中相同的动画效果:

 

let animation =
  Compose(
    Disc(Brushes.Green, 50, Rotating(PointF(0.f,0.f), 100.f)),
    Disc(Brushes.Red, 20, Linear(PointF(-100.f,0.f), PointF(100.f,0.f)))
  )

 

    这段代码创建一个树状结构的值,描述由两个盘子组成的动画。它指定每个对象如何随时间而改变位置,F# 的数据结构 AnimatedLocation 创建的对象是静态的,可以旋转,或沿着一条直线移动。

    当在 C# 中使用这种方法时,可以把这个差别联合类型重写为类层次。然后,通过创建一个对象树,获得类似的结果。在 C# 3.0 中,这由对象和集合初始值设定项功能,做了进一步简化:

 

var animation = new Compose(
  new Disc { Brush = Brushes.Green, Diameter = 50, Movement =
    new Rotating(new PointF(0.0f,0.0f), 100.0f) },
  new Disc { Brush = Brushes.Red, Diameter = 20, Movement =
    new Linear(new PointF(-100.0f, 0.0f), new PointF(100.0f, 0.0f) } }
);

 

    原理是相同的:声明性的库用于创建描述问题的值。在差别联合或集合和对象之间的选择,在很大程度上受语法影响,使得可以在宿主语言中创建最自然的代码。

    构建数据结构,这基本上是描述动画的消极方式。我们要看一种技术,使代码有更积极的感觉。