第十二章序列表达式和可选工作流
本章介绍
■生成和处理序列值
■处理 F# 序列表达式
■理解单子和 LINQ 表达式
■实现 F# 计算表达式
在我们开始讨论序列表达式之前,必须知道什么是序列(sequence),这也是数学的F# 术语。序列是有序的列表,可能包含无穷的元素。这一切听上去有点抽象,但也不用担心,我们已经熟悉这种类型了,在.NET 中表达同样概念的是:IEnumerable<T>。
在.NET 框架中有IEnumerable<T> 类型的主要原因,是它提供一种统一的方法来处理集合数据,比如,数组,词典,可变列表,不可变的F# 列表。在F# 中,我们将讨论序列,因为这是更通用的术语。序列可以表示有限元素的集合,也可以动态生成,在需要时恢复。我们将学习无穷序列,这听起来有些学术化,但是,在实际应用中也可能很有用。
我们首先看一下创建和处理序列的方法。传统的函数式方法是使用高阶函数,但是,现代语言通常提供了更容易的方法。在C# 中,我们可以使用迭代来生成序列,用LINQ 查询去处理已有的序列;而F# 语言把这两个概念统一起来,用序列表达式(sequence expressions)就能完成大部分操作。
在F# 中,序列表达式的语法并不是专为处理序列而设计的、单一用途的语言功能;它正是一个(非常有用!)更通用的结构的应用,称为计算表达式(computation expressions)。计算表达式写出的代码看起来像普通的 F#,但行为迥异。在序列表达式情况下,产生的结果序列不仅仅是一个值,我们将用示例来讨论,用计算表达式进行日志记录,更容易处理选项值。
注意
在很多方面,计算表达式能够自定义代码的含义,但也有一些限制。特别是,用计算表达式写的代码都必须编译成.NET 代码才能执行,而在其中,我们能自定义的基元(primitives)很少。它不能用于操作代码,在不同环境中执行,比如,就像LINQ to SQL 所做的。要在F# 中实现类似功能,我们必须组合本章的概念,一种称为F# 引用(F# quotations)的功能,本书并不讨论,在本书的网站上,可以找到有关引用的资源。
我们首先讨论序列,在熟悉了序列表达式以后,再讨论计算表达式,以及与C# 中的 LINQ 查询的关系。我们将从序列迈出第一步,在使用序列之前,要知道如何创建序列。