module Array: Arraytype'at ='a array
数组类型的别名。
val length : 'a array -> int返回给定数组的长度(元素数量)。
val get : 'a array -> int -> 'aget a n 返回数组 a 的第 n 个元素。第一个元素的编号为 0。最后一个元素的编号为 length a - 1。您也可以写 a.(n) 来代替 get a n。
Invalid_argument 如果 n 超出范围 0 到 (length a - 1)。val set : 'a array -> int -> 'a -> unitset a n x 就地修改数组 a,将第 n 个元素替换为 x。您也可以写 a.(n) <- x 来代替 set a n x。
Invalid_argument 如果 n 超出范围 0 到 length a - 1。val make : int -> 'a -> 'a arraymake n x 返回一个长度为 n 的新数组,并用 x 初始化。此新数组的所有元素最初在物理上都等于 x(在 == 谓词的意义上)。因此,如果 x 是可变的,则它在数组的所有元素之间共享,并且通过其中一个数组条目修改 x 将同时修改所有其他条目。
Invalid_argument 如果 n < 0 或 n > Sys.max_array_length。如果 x 的值为浮点数,则最大大小仅为 Sys.max_array_length / 2。val create_float : int -> float arraycreate_float n 返回一个长度为 n 的新浮点数数组,其数据未初始化。
val init : int -> (int -> 'a) -> 'a arrayinit n f 返回一个长度为 n 的新数组,其中第 i 个元素初始化为 f i 的结果。换句话说,init n f 将 f 应用于整数 0 到 n-1 的结果制成表格。
Invalid_argument 如果 n < 0 或 n > Sys.max_array_length。如果 f 的返回类型为 float,则最大大小仅为 Sys.max_array_length / 2。val make_matrix : int -> int -> 'a -> 'a array arraymake_matrix dimx dimy e 返回一个二维数组(数组的数组),第一维为 dimx,第二维为 dimy。此新矩阵的所有元素最初在物理上都等于 e。矩阵 m 的元素 (x,y) 使用表示法 m.(x).(y) 访问。
Invalid_argument 如果 dimx 或 dimy 为负或大于 Sys.max_array_length。如果 e 的值为浮点数,则最大大小仅为 Sys.max_array_length / 2。val init_matrix : int -> int -> (int -> int -> 'a) -> 'a array arrayinit_matrix dimx dimy f 返回一个二维数组(数组的数组),第一维为 dimx,第二维为 dimy,其中索引为 (x,y) 的元素初始化为 f x y。矩阵 m 的元素 (x,y) 使用表示法 m.(x).(y) 访问。
Invalid_argument 如果 dimx 或 dimy 为负或大于 Sys.max_array_length。如果 f 的返回类型为 float,则最大大小仅为 Sys.max_array_length / 2。val append : 'a array -> 'a array -> 'a arrayappend v1 v2 返回一个包含数组 v1 和 v2 连接的新数组。
Invalid_argument 如果 length v1 + length v2 > Sys.max_array_length。val concat : 'a array list -> 'a array与 Array.append 相同,但连接数组列表。
val sub : 'a array -> int -> int -> 'a arraysub a pos len 返回一个长度为 len 的新数组,包含数组 a 的第 pos 个到 pos + len - 1 个元素。
Invalid_argument 如果 pos 和 len 未指定 a 的有效子数组;也就是说,如果 pos < 0,或 len < 0,或 pos + len > length a。val copy : 'a array -> 'a arraycopy a 返回 a 的副本,即包含与 a 相同元素的新数组。
val fill : 'a array -> int -> int -> 'a -> unitfill a pos len x 就地修改数组 a,将 x 存储在第 pos 个到 pos + len - 1 个元素中。
Invalid_argument 如果 pos 和 len 未指定 a 的有效子数组。val blit : 'a array -> int -> 'a array -> int -> int -> unitblit src src_pos dst dst_pos len 将数组 src 中从第 src_pos 个元素开始的 len 个元素复制到数组 dst 中,从第 dst_pos 个元素开始。即使 src 和 dst 是同一个数组,并且源和目标块重叠,它也能正常工作。
Invalid_argument 如果 src_pos 和 len 未指定 src 的有效子数组,或者如果 dst_pos 和 len 未指定 dst 的有效子数组。val to_list : 'a array -> 'a listto_list a 返回 a 中所有元素的列表。
val of_list : 'a list -> 'a arrayof_list l 返回一个包含 l 中元素的新数组。
Invalid_argument 如果 l 的长度大于 Sys.max_array_length。val iter : ('a -> unit) -> 'a array -> unititer f a 依次将函数 f 应用于 a 的所有元素。它等价于 f a.(0); f a.(1); ...; f a.(length a - 1); ()。
val iteri : (int -> 'a -> unit) -> 'a array -> unit与 Array.iter 相同,但函数将元素的索引作为第一个参数应用,并将元素本身作为第二个参数应用。
val map : ('a -> 'b) -> 'a array -> 'b arraymap f a 将函数 f 应用于 a 的所有元素,并构建一个包含 f 返回结果的数组:[| f a.(0); f a.(1); ...; f a.(length a - 1) |]。
val map_inplace : ('a -> 'a) -> 'a array -> unitmap_inplace f a 将函数 f 应用于 a 的所有元素,并就地更新其值。
val mapi : (int -> 'a -> 'b) -> 'a array -> 'b array与 Array.map 相同,但函数将元素的索引作为第一个参数应用,并将元素本身作为第二个参数应用。
val mapi_inplace : (int -> 'a -> 'a) -> 'a array -> unit与 Array.map_inplace 相同,但函数将元素的索引作为第一个参数应用,并将元素本身作为第二个参数应用。
val fold_left : ('acc -> 'a -> 'acc) -> 'acc -> 'a array -> 'accfold_left f init a 计算 f (... (f (f init a.(0)) a.(1)) ...) a.(n-1),其中 n 是数组 a 的长度。
val fold_left_map : ('acc -> 'a -> 'acc * 'b) -> 'acc -> 'a array -> 'acc * 'b arrayfold_left_map 是 Array.fold_left 和 Array.map 的组合,它通过对 f 的调用传递累加器。
val fold_right : ('a -> 'acc -> 'acc) -> 'a array -> 'acc -> 'accfold_right f a init 计算 f a.(0) (f a.(1) ( ... (f a.(n-1) init) ...)),其中 n 是数组 a 的长度。
val iter2 : ('a -> 'b -> unit) -> 'a array -> 'b array -> unititer2 f a b 将函数 f 应用于 a 和 b 的所有元素。
Invalid_argument 如果数组大小不相同。val map2 : ('a -> 'b -> 'c) -> 'a array -> 'b array -> 'c arraymap2 f a b 将函数 f 应用于 a 和 b 的所有元素,并构建一个包含 f 返回结果的数组:[| f a.(0) b.(0); ...; f a.(length a - 1) b.(length b - 1)|]。
Invalid_argument 如果数组大小不相同。val for_all : ('a -> bool) -> 'a array -> boolfor_all f [|a1; ...; an|] 检查数组的所有元素是否都满足谓词 f。也就是说,它返回 (f a1) && (f a2) && ... && (f an)。
val exists : ('a -> bool) -> 'a array -> boolexists f [|a1; ...; an|] 检查数组中是否至少有一个元素满足谓词 f。也就是说,它返回 (f a1) || (f a2) || ... || (f an)。
val for_all2 : ('a -> 'b -> bool) -> 'a array -> 'b array -> bool与 Array.for_all 相同,但适用于二元谓词。
Invalid_argument 如果两个数组的长度不同。val exists2 : ('a -> 'b -> bool) -> 'a array -> 'b array -> bool与 Array.exists 相同,但适用于二元谓词。
Invalid_argument 如果两个数组的长度不同。val mem : 'a -> 'a array -> boolmem a set 当且仅当 a 在结构上等于 set 的某个元素时为真(即,set 中存在一个 x,使得 compare a x = 0)。
val memq : 'a -> 'a array -> bool与 Array.mem 相同,但使用物理相等而不是结构相等来比较数组元素。
val find_opt : ('a -> bool) -> 'a array -> 'a optionfind_opt f a 返回数组 a 中第一个满足谓词 f 的元素,如果数组 a 中没有满足 f 的值,则返回 None。
val find_index : ('a -> bool) -> 'a array -> int optionfind_index f a 返回 Some i,其中 i 是数组 a 中第一个满足 f x 的元素的索引,如果存在这样的元素。
如果不存在这样的元素,则返回 None。
val find_map : ('a -> 'b option) -> 'a array -> 'b optionfind_map f a 按顺序将 f 应用于 a 的元素,并返回第一个 Some v 形式的结果,如果不存在则返回 None。
val find_mapi : (int -> 'a -> 'b option) -> 'a array -> 'b option与 find_map 相同,但谓词将元素的索引作为第一个参数(从 0 开始计数)应用,并将元素本身作为第二个参数应用。
val split : ('a * 'b) array -> 'a array * 'b arraysplit [|(a1,b1); ...; (an,bn)|] 为 ([|a1; ...; an|], [|b1; ...; bn|])。
val combine : 'a array -> 'b array -> ('a * 'b) arraycombine [|a1; ...; an|] [|b1; ...; bn|] 等于 [|(a1,b1); ...; (an,bn)|]。如果两个数组长度不同,则抛出 Invalid_argument 异常。
val sort : ('a -> 'a -> int) -> 'a array -> unit根据比较函数,对数组进行升序排序。比较函数必须在其参数相等时返回 0,第一个参数大于第二个参数时返回正整数,第一个参数小于第二个参数时返回负整数(有关完整规范,请参见下文)。例如,compare 是一个合适的比较函数。调用 sort 后,数组将原地升序排序。sort 保证在恒定的堆空间和(最多)对数栈空间内运行。
当前实现使用堆排序。它在恒定的栈空间内运行。
比较函数的规范:令 a 为数组,cmp 为比较函数。对于 a 中的所有 x、y、z,以下必须为真
cmp x y > 0 当且仅当 cmp y x < 0cmp x y >= 0 且 cmp y z >= 0,则 cmp x z >= 0当 sort 返回时,a 包含与之前相同的元素,但重新排序,以便对于 a 的所有有效索引 i 和 j
cmp a.(i) a.(j) >= 0 当且仅当 i >= jval stable_sort : ('a -> 'a -> int) -> 'a array -> unit与 Array.sort 相同,但排序算法是稳定的(即比较相等的元素保持其原始顺序),并且不保证在恒定的堆空间内运行。
当前实现使用归并排序。它使用长度为 n/2 的临时数组,其中 n 是数组的长度。它通常比 Array.sort 的当前实现快。
val fast_sort : ('a -> 'a -> int) -> 'a array -> unit与 Array.sort 或 Array.stable_sort 相同,选择在典型输入上速度较快的那个。
val shuffle : rand:(int -> int) -> 'a array -> unitshuffle rand a 使用 rand 进行随机化,随机排列 a 的元素。排列的分布是均匀的。
rand 必须使得对 rand n 的调用返回范围 [0;n-1] 内的均匀分布随机数。Random.int 可用于此(不要忘记初始化生成器)。
val to_seq : 'a array -> 'a Seq.t按升序迭代数组。迭代期间对数组的修改将反映在序列中。
val to_seqi : 'a array -> (int * 'a) Seq.t按升序迭代数组,同时生成索引和元素。迭代期间对数组的修改将反映在序列中。
val of_seq : 'a Seq.t -> 'a array从生成器创建数组。
在从多个域并发访问数组时,必须小心:访问数组永远不会导致程序崩溃,但未同步的访问可能会产生令人意外的(非顺序一致的)结果。
每个访问多个数组元素的数组操作都不是原子的。这包括迭代、扫描、排序、分割和组合数组。
例如,考虑以下程序
let size = 100_000_000
let a = Array.make size 1
let d1 = Domain.spawn (fun () ->
Array.iteri (fun i x -> a.(i) <- x + 1) a
)
let d2 = Domain.spawn (fun () ->
Array.iteri (fun i x -> a.(i) <- 2 * x + 1) a
)
let () = Domain.join d1; Domain.join d2
执行此代码后,数组 a 的每个字段要么是 2,要么是 3,要么是 4,要么是 5。如果需要原子性,则用户必须实现自己的同步(例如,使用 Mutex.t)。
如果两个域仅访问数组的不同部分,则观察到的行为等效于来自这两个域的操作的一些顺序交错。
当两个域在没有同步的情况下访问相同的数组元素,并且至少一个访问是写入时,就会发生数据竞争。在没有数据竞争的情况下,观察到的行为等效于来自不同域的操作的一些顺序交错。
在可能的情况下,应通过使用同步来协调对数组元素的访问,从而避免数据竞争。
实际上,在存在数据竞争的情况下,程序不会崩溃,但观察到的行为可能不等于来自不同域的操作的任何顺序交错。然而,即使在存在数据竞争的情况下,读取操作也会返回对该位置的某些先前写入的值(浮点数组除外,存在一些例外情况)。
在存在数据竞争的情况下,浮点数组有两个补充注意事项。
首先,blit 操作可能会逐字节复制数组。此类 blit 操作与其他操作之间的数据竞争可能会产生令人意外的值,因为撕裂:部分写入与其他操作交错可能会创建在顺序执行中不存在的浮点值。
例如,在
let zeros = Array.make size 0.
let max_floats = Array.make size Float.max_float
let res = Array.copy zeros
let d1 = Domain.spawn (fun () -> Array.blit zeros 0 res 0 size)
let d2 = Domain.spawn (fun () -> Array.blit max_floats 0 res 0 size)
let () = Domain.join d1; Domain.join d2
res 数组可能包含既不是 0. 也不是 max_float 的值。
其次,在 32 位架构上,获取或设置字段涉及两个单独的内存访问。在存在数据竞争的情况下,用户可能会在任何操作上观察到撕裂。