F#基础教程 列表
F#中的列表是F#内置的简单集合类型。一个F#列表可以为空,用方括号代表([]),也可以是一组值的串联。你可以使用F#内置的操作符(::)串联一个列表。下面的例子给出一些示例,开始第一行为空列表,第二三行为使用(::)串联多个字符串的列表。
#light
let emptyList = []
let oneItem = "one " :: []
let twoItem = "one " :: "two " :: []
将值串联的语法有点冗长,因此,如果你只是想定义一个列表,可以使用如下简写。这种速记法将列表项放在方括号之间,并用分号(;)隔开。
#light
let shortHand = ["apples "; "pairs "]
F#有一个二元操作符(@),你可以用它连接两个列表,示例如下:
let twoLists = ["one, "; "two, "] @ ["buckle "; "my "; "shoe "]
在F#列表中所有的项目必须是同一类型。如果你尝试在列表中包含不同的类型,例如,尝试包含一个字符串和整数,你会得到一个编译错误。如果你需要一个混合类型的列表,你可以创建一个类型为obj(F#里的System.Object)的列表。如下示例。
#light
let emptyList = []
let oneItem = "one " :: []
let twoItem = "one " :: "two " :: []
let shortHand = ["apples "; "pairs "]
let twoLists = ["one, "; "two, "] @ ["buckle "; "my "; "shoe "]
let objList = [box 1; box 2.0; box "three"]
let printList l =
List.iter print_string l
print_newline()
let main() =
printList emptyList
printList oneItem
printList twoItem
printList shortHand
printList twoLists
for x in objList do
print_any x
print_char ' '
print_newline()
main()
执行结果:
one
one two
apples pairs
one, two, buckle my shoe
1 2.000000 "three"
F#的列表是不可变的(它也是值类型)。换句话说,一旦你创建一个列表,它就不能改变。函数与运算符并不改变他们,而是创建一个新的,另一个版本的列表,旧的列表以后仍可使用。下面的例子演示了这一点,创建一个包含单一字符串的F#列表,然后创建两个列表,每个都使用前一个做为基础串联。最后,List.rev函数应用于最后创建的列表执行逆转。当你打印这些列表时,可以看出,所有的列表都保持定义时而未改变。不必担心占用更多空间,不变量(值)对于垃圾回收程序是最易处理的。
#light
let one = ["one "]
let two = "two " :: one
let three = "three " :: two
let rightWayRound = List.rev three
let printList l =
List.iter print_string l
print_newline()
let main() =
printList one
printList two
printList three
printList rightWayRound
main()
执行结果:
one
two one
three two one
one two three
最常使用列表的是递归表达式。空列表代表基本情况,当函数接收一个空列表时,函数终止返回。当函数接收一个非空列表,它的第一项(头)被匹配处理,然后递归处理列表的其余部分(尾),下面示例演示了递归列表的使用。
#light
let listOfList = [[2; 3; 5]; [7; 11; 13]; [17; 19; 23; 29]]
let rec concatList l =
if List.nonempty l then
let head = List.hd l in
let tail = List.tl l in
head @ (concatList tail)
else
[]
let primes = concatList listOfList
print_any primes
首先,定义了由三个列表组成的F#列表。然后,定义一个递归函数concatList,其目的是合并列表中的列表为一个列表。该函数使用了F#库函数List.nonempty:检查F#列表是否为空。如果不为空,取列表头和列表尾,尾部调用函数本身,然后串联到头部;如果尾部为空,则返回空列表串联,因为空列表的串联对结果无影响。执行效果如下:
[2; 3; 5; 7; 11; 13; 17; 19; 23; 29]
concatList函数的定义比较冗长。幸运的是,F#包括一些针对于列表的模式匹配语法。将在以后章节介绍。