3.3.2 函数式列表

728 篇文章 1 订阅
349 篇文章 0 订阅
3.3.2 函数式列表


现在,我们已经适应了递归的一般概念,那么,可以详细地讨论函数式列表了。刚才我们提到过,列表可以为空,也可以由元素与另外的列表组成。因此,需要一个特殊的值来表示空列表,以及构建列表的方法,通过在已有列表的前面加上一个元素。第一个选项(空列表)有时称为 nil,第二个选项产生 cons cell(是构造列表单元的缩写,constructed list cell)。在图 3.1 中可以看到用空列表和 cons cell 构成列表的示例。
 
图 3.1 函数式包含列表 6、2、7 和 3。矩形表示 cons cell,包含一个值和对列表其余部分的引用;最后的cons cell 引用表示空列表的特殊值。


从图 3.1 中可以看出,每个 cons cell 保存列表的一个值(称为头),和对列表其余部分的引用(称为尾),它既可以是另一个 cons cell,也可以是空列表(nil)。我们现在看几个由 F# 提供的创建列表的方法:


> let ls1 = []
val ls1 : 'a list = []


> let ls2 = 6::2::7::3::[]
val ls2 : int list = [6; 2; 7; 3]


> let ls3 = [6; 2; 7; 3]
val ls3 : int list = [6; 2; 7; 3]


> let ls4 = [1 .. 5]
val ls4 : int list = [1; 2; 3; 4; 5]


> let ls5 = 0::ls4
val ls5 : int list = [0; 1; 2; 3; 4; 5]


首先,我们创建了一个空列表,在 F# 中写作 []。如果看看结果,就会发现 F# 创建了一个值,不包含元素。列表的类型是有点不清楚,因为,现在还不知道列表中会包含哪种类型的值,因此,F# 推断的类型为“某种”列表,这称为泛型值(generic value),我们将在第五章讨论。
第二个示例更加有趣。可以看到列表在后台是如何创建的:取一个空列表,使用创建 cons cell 的语法 ::。与[一般的]运算符,例如 +,不同,:: 结构是右关联的,即,从右到左构成值。如果按这个方向读表达式,可以看到,我们用 3 和一个空列表,构建了一个列表单元;然后,用 7 和这个结果,构建另一个单元,等等。输入这个表达式以后,F# Interactive 报告,创建了一个 int list 类型的列表。表示值 ls2的类型是包含整数的列表。这还可以使用泛型类型完成,你可能从 C# 中学过(如何在 F# 中使用它们,在后面会有详细讨论)。
接下来的两个示例,我们使用了 F# 为创建列表提供的语法糖(syntactic sugar)。第一个示例使用方括号,列表元素以分号分隔;第二个示例使用 .. 创建包含数字序列的列表。
最后一个例子使用 cons cells 创建列表,把值添加到另一个列表的开头。可以看到,ls5 第一个元素是 0,后面的所有元素来自列表 ls4。
函数式列表的一个重要特征是不可变。就是说,我们可以构建一个列表(比如前面的示例),但不能对已有的列表进行修改;不能添加或删除元素。添加新元素或删除已有元素的函数,总是返回一个新的列表,而不修改原始列表,事实上,修改列表是不可能的。我们将在第五、第六和第十章看到更多有关这类函数的示例,但现在,我们要讨论如何处理现有列表中的元素。
处理函数语言中的列表,典型的代码包含两个分支:
■ 当给定的列表为空时,执行的操作
■ 当参数是 cons cell 时,执行的操作
后一个分支通常对列表的头进行计算,并递归处理列表的尾。在这一章的后面,我们将会看到所有的常用模式,现在,我们研究一下如何写代码,使用模式匹配在两个分支之间进行选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值