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