3.3.2.1 用模式匹配分解列表

728 篇文章 1 订阅
349 篇文章 0 订阅

3.3.2.1 用模式匹配分解列表

 

在 3.2.4 节,我们讨论有关元组的匹配模式时,看到两种不同的使用方法。一种方法是直接在 let 绑定中写出模式,即可以把表达式的结果分配给值,也可以在函数参数的声明中;另一种方法是使用 match 关键字。两者的重要区别在于,使用 match 可以指定多个模式,有多个分支。处理列表,我们需要使用第二种方法,因为在列表处理时,每次都要指定两个不同的分支,(一个用于空列表,另一个用于使用 cons cell 创建的列表)。

下面的代码演示了在列表上的模式匹配,输出的消息是第一个元素的值,如果列表为空,则“Empty list”:

 

match list with

| []       -> printfn "Empty list"

| head::tail -> printfn "Startingwith %d" head

 

可以看到,在第二行的模式匹配空列表,在第三行的模式,提取列表的头(第一个元素的值)和列表的尾(列表头后面的部分)。这两个模式的语法与前面创建列表的语法完全相同。空列表用 [] 来匹配,cons cell 使用:: 模式分解。第二种情况更重要,因为它把值分配给两个新的符号,head 和 tail,将包含通过分解第一个 cons cell 获得的一个数字,和列表的其余部分。空列表不含任何值,因此,第一个模式不绑定值到任何符号,它只会通知我们原始列表是空的。

如果参考图 3.1,就会发现,第一个模式对应于椭圆nil,不包含任何值;第二个模式匹配矩形cons cell,包含两个部分的内容。

和元组一样,列表也是完整模式,就是说,对于任意给定的列表,总会选择一个分支,不可能失败。现在,如果我们尝试使用不完整模式,看看会发生什么。

 

清单 3.13 列表上的不完整模式匹配 (F# Interactive)

> let squareFirst list =

  matchlist with

  |head::_ -> head * head

;;

Warning FS0025: Incomplete pattern matcheson this  |  [1]

expression. The value '[]' will not bematched.        |

val sqareFirst : int list –> int       <-- 取列表,返回整数

 

> squareFirst [4; 5; 6];;  [2]

val it : int = 16

 

> squareFirst []    [3]

Exception of type 'Microsoft.FSharp.Core.  |  运行时,抛出异常

MatchFailureException' was thrown.      |

(...)

 

我们首先声明一个函数 squareFirst,只包含一个模式匹配,匹配 cons cell,返回列表中的第一个元素的平方。然而,当列表为空时,此模式不能处理这种情况。我们可以看到,F# 编译器是很聪明的,当我们写的模式匹配可能会失败时,它能检测到这种情况,甚至为我们提供了匹配失败的样本[1]。通常不应该忽略这种警告,除非你绝对有把握永远不会发生这种情况。即使对于空列表,函数没有任何合理的意义,最好还是处理这种情况(模式可以使用下划线字,表示匹配任意值),可以抛出附带信息的异常,也可什么都不做。当然,如果函数的返回类型是除 unit 以外的其他任何类型,即使什么也不做,也必须给出一个适当的返回值。如果函数真的不应该调用空列表,那么,最好的办法是抛出异常。

尽管有警告,F# Interactive 还是能够处理,因此,我们可以尝试调用这个函数。首先,尝试一种可以工作的情况[2],我们会看到,它的行为与预期相同。如果用空列表作为参数调用函数[3],因为match 构造不包含任何匹配的模式,所以将抛出异常。这是通常的 .NET 异常,在 F# 中可以使用 try 结构捕获到。

你可能会想,我们能从函数式列表中得到什么,因此,在下一节,我们会把注意力转到 C#,并用它来详细解释列表;我们还会写出第一段列表处理的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值