The faulty place in your code is
let b =
Array.make dim (Array.make dim 0)
which does not what you intend. The name b is not in your code but is convenient for the discussion. To understand what you see, let us rewrite this code in the following equivalent manner:
let b =
let a = Array.make dim 0 in
Array.make dim a
This code produces an array of length dim whose entries are all a. These are not copies of a, they are just a with kind of a different name. The proper way to express this in OCaml is to say that these structures are physically equal and the == operator tests for physical equality.
# b.(0) == b.(1);;
true
Physical equality is a stronger relation than structural equality tested by the more usual = operator. It is specified that given two physically equal mutable structures like b.(0) and b.(1), the modification of any of them will also affect the other one, or in the words of the documentation of the Pervasives module:
val (==) : 'a -> 'a -> bool
e1 == e2 tests for physical equality of e1 and e2. On mutable types such as references, arrays, byte sequences, records with mutable fields and objects with mutable instance variables, e1 == e2 is true if and only if physical modification of e1 also affects e2. On non-mutable types, the behavior of ( == ) is implementation-dependent; however, it is guaranteed that e1 == e2 implies compare e1 e2 = 0.
We can think to this as a formal way to say that these two structures are “really the same”.
If you want to fox the structure of your code, you can take advantage of the Array.make_matrix function which will generate a fresh 2-dimensional array. If you are tired of debugging errors in for-loops, you can use the more ocaml-ish solution:
let unpack dim a =
let line i =
Array.init dim (fun j -> a.(i*dim + j))
in
Array.init dim line
let to_array2d a =
let dim = int_of_float (sqrt (float (Array.length array1d))) in
unpack dim a
See Also