日期:2010-01-30 浏览次数:20647 次
创建一个list:
语法 | 描述 | 示例 |
[] | 空list | [] |
expr :: expr | 将一个项加入一个list | 1 :: [2; 3] |
[expr; ...; expr] | 列举项创建list | [1; 2; 3] |
[expr .. expr] | 连续的数字 | [1 .. 99] |
[ for x in list ... ] | 通过运算生成list(类似于Linq里的select) | [ for x in 1..99 -> x * x ] |
expr @ expr | 合并两个list | [1; 2] @ [3] |
操作示例:
let oddPrimes = [3; 5; 7; 11]
let morePrimes = [13; 17]
let primes = 2 :: (oddPrimes @ morePrimes)
val primes : int list = [2; 3; 5; 7; 11; 13; 17]
list同样是不可变的(immutable):操作符“::”并未真正改变原list本身,相反的,它创建了一个新的list。示例:
> let people = [ "Adam"; "Dominic"; "James" ];;
val people : string list
> people;;
val it : string list = [ "Adam"; "Dominic"; "James" ]
> "Chris" :: people;;
val it : string list = [ "Chris"; "Adam"; "Dominic"; "James" ]
> people;;
val it : string list = [ "Adam"; "Dominic"; "James" ]
如你所见,people并未被改变。在内存中,F#将list表示为关联的list;每个F#的list的值(value)包含了自身的值以及指向下一个列表的指针。也就是说当你使用“::”来创建一个新的list的时候,新list的尾部就包含了一个指向老list的指针。
在我看来,通过不可变性与指针的结合,提高了list的内存利用效率。
我们再看一个分解(decompose)list的例子:
let oddPrimes = [3; 5; 7; 11]
let printFirst primes =
match primes with
h :: t -> printfn "The first prime in the list is %d" h
[] -> printfn "No primes found in the list"
> printFirst oddPrimes;;
The first prime in the list is 3
val it : unit = ()
程序通过h::t来分解list,h代表list的第一个元素,t代表其后续。[]代表空list。match是匹配开始关键字,primes是匹配源,通过表示各种匹配条件。感觉类似于switch case。
F#包含了一个List模块。其提供了一些功能:
方法 | 类型 | 描述 |
List.length | 'T list -> int | 返回list长度 |
List.head | 'T list -> 'T | 返回非空list的第一个元素 |
List.tail | 'T list -> 'T list | 返回非空list中除了第一个元素外的其他所有元素 |
List.init | int -> (int -> 'T) -> 'T list | 通过一个可以通过索引生成值的函数来构造一个定长list |
List.append | 'T list -> 'T list -> 'T list | 返回一个合并后的list |
List.filter | ('T -> bool) -> 'T list -> 'T list | 返回一个新的过滤后的列表。 |
List.map | ('T -> 'U) -> 'T list -> 'U list | 将一个list通过一个转换函数转换为另一个list |
List.iter | ('T -> unit) -> 'T list -> unit | 对list中的每个项执行一次指定的函数 |
List.unzip | ('T * 'U) list -> 'T list * 'U list | zip操作的反向操作 |
List.zip | 'T list -> 'U list -> ('T * 'U) list | 将两个拥有相同长度的list合并成一个新的list,相同index的项会组合成元组(tuple),并作为新list中的项。 |
List.toArray | 'T list -> 'T[] | 从一个list生成一个array |
List.ofArray | 'T[] -> 'T list | 从一个array生成一个list |
上面的说明还都是比较抽象的,示例如下:
> List.head [5; 4; 3];;
val it : int = 5
> List.tail [5; 4; 3];;
val it : int list = [ 4; 3 ]
> List.map (fun x -> x*x) [1; 2; 3];;
val it : int list = [ 1; 4; 9 ]
> List.filter (fun x -> x % 3 = 0) [2; 3; 5; 7; 9];;
val it : int list = [ 3; 9 ]
从上例可得知,我们可以使用fun关键字来表示匿名函数。
一些通用的不可变数据结构
数据类型大概可以分为可变(mutable)的和不可变(immutable)的两种。不可变类型有时会被称为持久(persistent)或函数体(functional)。F#中常用的不可变类型:
· 元组(Tuple)和选项(option):他们都是不可变类型并且是F#的基本(basic workhorse)
· 不可变链表’T list:非常适合从左至右的便利。但不适合随机