4

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

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

我只想将 1 分配给 a[0][1] 但后来事情发生了:第一列中的所有元素都已分配。即a[0][1]、a[1][1]、a[2][1]、a[3][1]和a[4][1]在代码后都等于1以上执行。
如果我使用以下方法创建数组:

Array.make_matrix 5 5 0

一切都很好。

我的环境:

Ubuntu 13.10
Ocaml 4.01.0
open Core.Std 
4

3 回答 3

7

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

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

正确的代码应该是

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

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

你应该检查这个 Q/A:Ocaml - Accessing components in a array of records

于 2013-12-12T02:21:02.110 回答
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一些较小的类型,如charand bool,以及具有所有无参数构造函数的代数数据类型,都被实现为值类型。但值类型在语义上等同于不可变引用类型,除了物理相等性。所以你可以将所有类型视为为简单起见,引用类型。)

于 2013-12-12T06:40:50.913 回答
2

Just for more information:

Here is the doc of Array: http://caml.inria.fr/pub/docs/manual-ocaml/libref/Array.html

val make : int -> 'a -> 'a array
Array.make n x returns a fresh array of length n, initialized with 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.
Raise Invalid_argument if n < 0 or n > Sys.max_array_length. If the value of x is a floating-point number, then the maximum size is only Sys.max_array_length / 2.

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

于 2013-12-12T11:59:12.627 回答