OCaml中Array.create的奇怪之处

时间:2013-12-12 01:37:24

标签: ocaml ocamlbuild

我是OCaml的新手。当我在Ocaml中使用数组进行编码时,我遇到了一个我无法理解的问题 这是代码:

let a = Array.create 5 (Array.create 5 0);
a.(0).(1) <- 1

我只想将1分配给[0] [1],但事情发生了:第一个colummn中的所有元素都已分配。也就是说,代码后[0] [1],[1] [1],[2] [1],[3] [1]和[4] [1]都等于1以上执行。
如果我使用:

创建数组
Array.make_matrix 5 5 0

一切都很好。

我的环境:

Ubuntu 13.10
Ocaml 4.01.0
open Core.Std 

3 个答案:

答案 0 :(得分:6)

这是Array.create的常见缺陷。当你的数组元素被装箱时,请使用Array.init。

Array.create使用相同的值初始化数组元素:如果值被加框,则使用相同的指针。在您的情况下,所有元素a.(i)都指向由Array.create 5 0创建的相同数组。

正确的代码应该是

let a = Array.init 5 (fun _ -> Array.create 5 0)

这会创建5个单独的数组。

您应该查看此问答:Ocaml - Accessing components in an array of records

答案 1 :(得分:4)

你只调用Array.create两次,所以只创建了两个数组 - 一个数组都指向另一个数组。

Array.create创建一个数组,并将每个元素设置为给定值的副本。所以就好像你这样做了:

let x = Array.create 5 0;
let a = Array.create 5 <some dummy value>;
a.(0) <- x;
a.(1) <- x;
a.(2) <- x;
a.(3) <- x;
a.(4) <- x;

看到问题?所有五个元素都设置为x,指向同一个数组的指针。

请注意,OCaml中的所有类型基本上都是引用类型。 (从技术上讲,int和一些较小的类型(如charbool)以及带有所有无参数构造函数的代数数据类型都是作为值类型实现的。但值类型在语义上等同于不可变引用类型,除了物理相等。因此,为简单起见,您可以将所有类型视为引用类型。)

答案 2 :(得分:2)

仅供参考:

这是Array的文档:http://caml.inria.fr/pub/docs/manual-ocaml/libref/Array.html

val make:int - &gt; 'a - &gt; '阵列
Array.make n x返回一个长度为n的新数组,用x初始化。 All the elements of this new array are initially physically equal to x (in the sense of the == predicate). Consequently, if x is mutable, it is shared among all elements of the array, and modifying x through one of the array entries will modify all other entries at the same time
如果n&lt;则提高Invalid_argument 0或n> Sys.max_array_length。如果x的值是浮点数,则最大大小仅为Sys.max_array_length / 2.

val create : int -> 'a -> 'a array
Deprecated. **Array.create is an alias for Array.make**.