3.2.4 模式匹配元组

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

3.2.4 模式匹配元组

 

在前面的示例中,我们是在 let 绑定中用模式匹配分解元组的,清单 3.10 的代码可以稍微改进一下。我们实际上并不使用元组中的第二个元素,因此,只需要把第一个元素指定一个名字。在模式中把第二个值写成下划线,就可以做到,像这样:

 

let (originalItem1, _) = tuple

 

下划线是一种特殊的模式,能匹配任何表达式,并且忽略赋给它的值。在 let 绑定中使用模式匹配,通常是非常有用的,另外还有很多地方也可以使用。事实上,模式几乎可以出现在任意需要把表达式指定给值的地方。模式匹配另一个极为有用的地方是,指定函数的参数。可以使用模式,而不需要参数的名字。这样,withItem2 函数就更简单了:

 

let withItem2 newItem2 (originalItem1, _) =(originalItem1, newItem2)

 

现在我们已经把声明从三行缩减到一行,结果没有使用任何不需要的值,能够清晰地显示出数据在代码中的流动。单从代码就能看到原始元组中的第一个元素被复制(通过跟踪符号 originalItem1 的使用),另一个函数参数成为返回元组的第二个元素(通过跟踪 newItem2 的使用)。在后面我们写的大多数 F# 函数中,首选使用这种处理元组的方法。

模式匹配的另一种常见用法是用在 F# 的match表达式中,我们在 2.4.3 节中已经看过了。这样,我们可以使用 match 表达式,重写 withItem2 函数:

 

let withItem2 newItem2 tuple =

  matchtuple with

  |(originalItem1, _) -> (originalItem1, newItem2)

 

match 结构能够根据模式匹配指定的表达式 (tuple),模式以竖线开头,可以是一个或多个。在我们的示例中,只有一个模式,因为有两个元素组成的任何元组,都可以把它的元素分解到两个值中,运行总是沿着这个唯一的分支。F# 编译器分析模式匹配,推断出参数值 tuple 是元组类型,包含两个元素。

 

注意

 

记住,不能使用模式匹配来判断一个元组是包含两个、还是三个元素,这会导致编译时错误,因为模式的类型必须和根据模式匹配的表达式的类型相同,这样,包含三个元素的元组类型(例如,int * int * int)与包含两个元素的元组(例如,int * int),它们的类型不兼容。模式匹配只能用来确定值的运行时属性;元组中的元素个数由元组的类型决定,在编译时检查。如果想知道如何表示有几个不同值的数据类型,要等到第五章,使用差别联合(discriminated unions)。

 

在前面的示例中,我们使用了一种不会失败的模式,因为,所有包含两个元素的元组都可以分解为单独的元素。在 F# 中,被称为完整模式(complete pattern)。如果模式不完整,就可能会失败,这时,match 结构就特别有用的,我们可以指定几个不同的模式(每个模式占一行,以竖线开头);如果第一个模式失败,就尝试下一个模式,直到找到成功的模式为止。

对元组来说,不完整模式是什么呢?好的,我们可以写一个模式,只匹配某些特定值的第一个元素(城市名称)。比如说,在纽约有 100 人从来没有被统计过,因此,当设置元组的第二个元素(城市的人口)时,如果是纽约,我们就要加上 100。可以用 if 表达式来,而清单 3.11 提供了更优雅的解决方案,使用模式匹配。

 

清单 3.11 有多个模式的模式匹配 (F# Interactive)

 

> let setPopulation tuple newPopulation=

   matchtuple with

   |("New York", _) -> ("New York", newPopulation + 100)  [1]

   |(cityName, _) -> (cityName, newPopulation)          [2]

;;

val setPopulation : string * 'a -> int-> string * int

 

> let prague = ("Prague", 123)

setPopulation prague 10;;

val it : string * int =("Prague", 10)

 

> let ny = ("New York", 123)

setPopulation ny 10;;

val it : string * int = ("NewYork", 110)

 

清单 3.11 中的 match 表达式包含两个不同的模式。第一个包含的元组,第一个元素是字符串“New York”作为,第二个元素是下划线[1]。这样,它只匹配第一个元素为“New York”、第二个元素为任意值的元组。当匹配这个模式时,返回代表纽约元组,但人口比给定参数值多 100。第二个模式[2] 与前面的示例中的相同,设置元组的第二个元素。

示例中函数声明后面的代码行为正如预期。如果尝试设置 Prague 的新人中,人口的新值就被使用;但当我们对 New York 尝试执行这个操作时,人口的新值会增加 100。

因为元组的简单,在开发的早期,经常使用。在下一节,我们将看另一个基本的不可变数据类型:列表。我们已经看到,元组表示元素已知[的数据],但类型可以不同;而列表正好相反:列表表示元素数目未知,但类型相同[的数据]。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值