3.2.1.1 在 F# 中使用元组
让我们看一个更复杂的 F# 使用元组的代码。在清单 3.5 中,使用元组存储有关城市的信息。第一个成员是字符串(城市的名字),第二个成员是整数,包含住在城市的人口。我们实现的函数 printCity,输出城市名字与人口的消息,最后,创建两个城市并打印有关信息。
清单 3.5 使用元组 (F# Interactive)
> let printCity(cityInfo) = |
printfn "Population of %s is %d." | [1]
(fst cityInfo) (snd cityInfo) |
;;
val printCity : string * int –> unit <- 显示函数的类型
> let prague = ("Prague",1188126) | [2]
let seattle = ("Seattle", 594210) |
;;
val prague : string * int | 创建两个元组值
val seattle : string * int |
> printCity(prague) | [3]
printCity(seattle);; |
Population of Prague is 1188126.
Population of Seattle is 594210.
清单 3.5 展示的是 F# Interactive 会话,因此,我们自己也可以轻松地尝试。第一段代码[1]声明了函数 printCity,把cityInfo(城市的信息)作为参数,用标准的 F# printfn 函数输出参数值,格式字符串指定第一个参数是字符串,第二个是整数。读取元组中的第一、第二个元素,可以使用两个标准的 F# 函数,fst 和 snd(很显然表示 first 和 second)。
下一行显示了由 F# 类型推断推导出的函数类型。可以看到,这个函数的参数为元组(使用星号表示:string * int),不返回任何值(箭头符号的右边表示成 unit 类型),这正是我们所希望得到的。
接下来,我们创建了两个元组值[2],保存 Prague 和 Seattle的人口信息。在 F# Interactive shell 中输入这些行后,控制台(把 shell 翻译成外壳,怎么得觉得不是很直观明了。)会输出新声明值的类型,可以看到,这两个值都是元组类型,与 printCity 函数参数的类型相同,因此,我们可以把这两个值作为参数,传递给打印函数,能得到预期的结果[3]。
我们承诺过,用 C# 一样能够实现这个示例,现在就来兑现这一承诺。
使用元组时的类型检查
元组的类型与函数的参数类型相匹配,这一点非常重要的,否则,如果两种类型不兼容,就无法调用函数。这了说明这一点,可以尝试在 F# Interactice 控制台中输入以下代码:
let newyork = ("New York",7180000.5)
printCity(newyork)
我们还不能确定纽约怎么会有 7,180,000.5 的居民,但如果是这种情况,元组 newyork 的类型就不可能是 string * int,而应该是 string * float,因为这是类型推断根据元组的第二个元素是浮点数作出的正确推导。如果这样做了,将会看到第二行不是有效的 F# 代码,编译器会报错,说类型不兼容。