3.2.3 计算元组
目前为止,在这个示例中到,我们还只是创建了几个元组,打印其值,现在,让我们进行一些计算。由于过去一年添加大量的新生儿,我们可能想要增加居民人数。
如你所知,元组类型是不可变的,因此,我们不能设置 C# 元组类的属性。在 F# 中,可以使用两个函数 (fst 和 snd),读取元组值,但是,没有函数来设置值,所以,这种情况是类似的。这意味着,我们计算将必须遵循通常的函数模式,由原来的城市名,从最初的元组和人口增量复制,返回一个新的元组。
清单 3.9 显示了在 C# 中如何做到的。不像清单 3.7 中添加方法到 Tuple<T1, T2> 类,我们作为扩展方法实现它。这种方式,我们可以使用这个方法,带有 .NET 4.0 库中现成的密封的元组类型。
Listing 3.9 Incrementing the population of a city (C#)
static class TupleExtensions {
public static Tuple<T1, T2> WithItem2<T1, T2>
(this Tuple<T1, T2> tuple, T2 newItem2) {
return Tuple.Create(tuple.Item1, newItem2);
}
}
var pragueOld = Tuple.Create("Prague", 1188000);
var pragueNew = pragueOld.WithItem2(pragueOld.Item2 + 13195);
PrintCity(pragueNew);
WithItem2 方法取第二个元素的新值作为参数值,使用 Tuple.Create 方法来创建新的元组,第一个元素从当前的元组(this.item1)和第二个元素设置为新值 newItem2 复制而来。该清单还显示了如何使用这个方法。我们创建关于 Prague 的城市信息,增加了 13195 后,得到下一年新的人口值。
现在,我们想在 F# 中做同样的事情,将编写函数 withItem2 (清单 3.10),这与前面的 C# 示例中的 WithItem2 方法完全相同。
Listing 3.10 Incrementing the population of a city (F#)
let withItem2 newItem2 tuple =
let (originalItem1, originalItem2) = tuple
(originalItem1, newItem2)
let pragueOld = ("Prague", 1188000)
let pragueNew = withItem2 (snd(pragueOld) + 13195) pragueOld
printCity(pragueNew)
清单 3.10 首先实现函数 withItem2。可以只使用 fst 函数来实现,它读取元组中第一个元素的值,但我们想要演示 F# 的另一个可以用于元组功能:模式匹配。你会看到这个函数的内部,我们首先把给定的元组分解为参数值,给两个单独的值。这就是模式匹配的地方,在等号的左侧,可以看到一种语言结构,叫”模式”,在右侧有一个表达式,根据模式进行匹配。模式匹配取表达式的值,将它分解成在模式中使用的值。
在下一行,我们可以使用 originalItem1,通过模式匹配,从元组中提取。我们使用第一个元素的原始值,由给定的参数值(newItem2)作为第二个元素的新值,重建这个元组。(在下一节中,我们将看到更多对元组进行匹配的模式的示例)。除了使用模式匹配,该代码没有显示任何新的内容, 但模式匹配是一个重要的主题,F# 提供了其他使用元组的方法。让我们仔细看看。
----------
[3] 对"类型参数"、"方法参数",等等,引起的混乱,我真诚的道歉。
有时,在规范中定义的术语,不允许优美的散文。