Lists
F#中List类型类似集合类型。list可以是空的list,用方括号[]表示。F#中可以连结值,使用量过冒号::把值串联一个list中。
let emptyList = []
let oneItem = "one " :: []
let twoItem = "one " :: "two " :: []
最后一个必须要是list,不管是不是空的。
上述采用连结的方式定义比较冗长,可以使用快捷方式定义list,只需要在[]中用分号分割元素就行了。
let
shortHand
=
[
"apples "
;
"pears"
]
使用@操作符可以把2个list合并为1个。
let twoLists = ["one, "; "two, "] @ ["buckle "; "my "; "shoe "]
list中元素的类型必须是一致的。
使用List
F#中list通常用于模式匹配或者递归。从list中取出第一个元素的语法和连结一个元素到list中是一样的。
由一个标识符表示head,后面2个冒号,接下来一个标识符表示剩下的list。如下面的例子:
// list to be concatenated
let listOfList = [ [ 2 ; 3 ; 5 ] ; [ 7 ; 11 ; 13 ] ; [ 17 ; 19 ; 23 ; 29 ] ]
// definition of a concatenation function
let rec concatList l =
match l with
| head :: tail -> head @ (concatList tail )
| [ ] -> [ ]
// call the function
let primes = concatList listOfList
// print the results
printfn "%A" primes
let listOfList = [ [ 2 ; 3 ; 5 ] ; [ 7 ; 11 ; 13 ] ; [ 17 ; 19 ; 23 ; 29 ] ]
// definition of a concatenation function
let rec concatList l =
match l with
| head :: tail -> head @ (concatList tail )
| [ ] -> [ ]
// call the function
let primes = concatList listOfList
// print the results
printfn "%A" primes
遍历List
//遍历list
let rec visit l =
match l with
| head :: tail ->
printfn "%i" head
visit tail
| [ ] -> ( )
// some test data
let testSequence = [ 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; ]
// call the function
visit testSequence
let rec visit l =
match l with
| head :: tail ->
printfn "%i" head
visit tail
| [ ] -> ( )
// some test data
let testSequence = [ 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; ]
// call the function
visit testSequence
结果如下:
取出list的头,递归的处理剩下的list,这在模式匹配中是常用的方法。但不是仅有的方法。下面也是几种常用的方法。
// function that attempts to find various sequences
let rec findSequence l =
match l with
// match a list containing exactly 3 numbers
| [x ; y ; z ] ->
printfn "Last 3 numbers in the list were %i %i %i" x y z
// match a list of 1, 2, 3 in a row
| 1 :: 2 :: 3 :: tail ->
printfn "Found sequence 1, 2, 3 within the list"
findSequence tail
// if neither case matches and items remain
// recursively call the function
| head :: tail -> findSequence tail
// if no items remain terminate
| [ ] -> ( )
// some test data
let testSequence = [ 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ; 8 ; 7 ; 6 ; 5 ; 4 ; 3 ; 2 ; 1 ]
// call the function
findSequence testSequence
let rec findSequence l =
match l with
// match a list containing exactly 3 numbers
| [x ; y ; z ] ->
printfn "Last 3 numbers in the list were %i %i %i" x y z
// match a list of 1, 2, 3 in a row
| 1 :: 2 :: 3 :: tail ->
printfn "Found sequence 1, 2, 3 within the list"
findSequence tail
// if neither case matches and items remain
// recursively call the function
| head :: tail -> findSequence tail
// if no items remain terminate
| [ ] -> ( )
// some test data
let testSequence = [ 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ; 8 ; 7 ; 6 ; 5 ; 4 ; 3 ; 2 ; 1 ]
// call the function
findSequence testSequence
上例中,第一个匹配规则匹配固定长度的list,只含有3个元素的list。
第二个匹配规则,是检测是否有序列1,2,3在list中。
最后2个规则是标准的head/tail处理。
结果如下:
对list中每个元素做操作,F#核心库包含有一个函数 map,定义在List模块中,它的定义如下:
let
rec
map func list
=
match list with
| head :: rest ->
func head :: map func rest
| [ ] -> [ ]
match list with
| head :: rest ->
func head :: map func rest
| [ ] -> [ ]
所以,可以有如下的写法:
let
addfunc i
=
i + 1
let alist = [ 1 ; 2 ; 3 ]
let blist =map addfunc alist
printfn "%A" blist
i + 1
let alist = [ 1 ; 2 ; 3 ]
let blist =map addfunc alist
printfn "%A" blist
结果如下:
List Comprehensions
这个术语不知道怎么翻译贴切,没找到合适的中文翻译。
维基百科的描述:
A list comprehension is a syntactic construct available in some programming languages for creating a list based on existing lists.
大意就是list comprehension一个语法的结构,它能基于一个已经存在的list创建一个list。
看到一句话,可能更加贴切:
"A List Comprehension is a way to apply some function to every member of a list."
F#中的sequence,list和array可以直接使用comprehension语法。Sequences是类型序列的集合,也就是.NET BCL(基础类库)中的IEnumerable类型在F#中的名称。
最简单的comprehension应用是指定范围。如下例子:
let
numericList
=
[
0
..
9
]
let alpherSeq = seq { 'A' .. 'Z' }
let multiplesOfThree = [ 0 .. 3 .. 30 ]
let revNumericSeq = [ 9 .. - 1 .. 0 ]
printfn "%A" numericList
printfn "%A" alpherSeq
printfn "%A" multiplesOfThree
printfn "%A" revNumericSeq
let alpherSeq = seq { 'A' .. 'Z' }
let multiplesOfThree = [ 0 .. 3 .. 30 ]
let revNumericSeq = [ 9 .. - 1 .. 0 ]
printfn "%A" numericList
printfn "%A" alpherSeq
printfn "%A" multiplesOfThree
printfn "%A" revNumericSeq
List comprehensions允许从一个集合上,循环创建集合。只需要用for。如下代码
// a sequence of squares
let
squares
=
seq { for x in 1 .. 10 -> x * x }
// print the sequence
printfn "%A" squares
let list =
[ for x in 1 .. 10 -> x * x ]
// print the list
printfn "%A" list
注意使用seq和list打印的结果有些差别。
seq { for x in 1 .. 10 -> x * x }
// print the sequence
printfn "%A" squares
let list =
[ for x in 1 .. 10 -> x * x ]
// print the list
printfn "%A" list
注意使用seq和list打印的结果有些差别。
F#使用yield关键字,可以更加灵活的控制哪个元素可以生成,那个不需要生成。如下代码:
// a sequence of even numbers
let evens n =
seq { for x in 1 .. n do
if x % 2 = 0 then yield x }
// print the sequence
printfn "%A" (evens 10 )
let squarePoints n =
seq { for x in 1 .. n do
for y in 1 .. n do
yield x, y }
// print the sequence
printfn "%A" (squarePoints 3 )
let evens n =
seq { for x in 1 .. n do
if x % 2 = 0 then yield x }
// print the sequence
printfn "%A" (evens 10 )
let squarePoints n =
seq { for x in 1 .. n do
for y in 1 .. n do
yield x, y }
// print the sequence
printfn "%A" (squarePoints 3 )