奇怪的行为存储函数导致 OCaml

Strange behavior storing function results in OCaml

请考虑以下两个模块。模块 a.ml 包含:

(* Calls f with multi-indices ranging from beginning multi-index, args,
   to the max multi-index (current arg is index). *)
let rec do_multi_call max_mindex ~f args index = 
  let dim = Array.length max_mindex in
  if dim = 0 then
    f args                                                                                                                                                               
  else (
    let rest = Array.sub max_mindex 1 (pred dim) in
    args.(index) <- 0;
    while (args.(index) <= max_mindex.(0)) do
      do_multi_call rest ~f args (succ index);
      args.(index) <- succ (args.(index));
    done )

(* Calls f with m-indices ranging from 0 to max_mindex. *)
let multi_call (max_mindex : int array) ~f =
  let n_indices = Array.length max_mindex in
  let initial_args = Array.make n_indices 0 in
  do_multi_call max_mindex f initial_args 0

模块 b.ml 包含:

open A

(* print int arrays *)
let print_index i = 
  Array.iter (Printf.printf "%d ") i;
  print_endline ""; in                                                                                

let d = [| 2 ; 3 |] in
let indices = Queue.create () in
let add_index i = ( 
  print_index i;
  Queue.add i indices) in
multi_call d add_index;
print_endline ""; 
Queue.iter print_index indices;

目标是生成从[| 0 ; 0 |][| 2 ; 3 |]的所有数组,存储在b.ml中的indices中。但是,我得到的输出是

0 0 
0 1 
0 2 
0 3 
1 0 
1 1 
1 2 
1 3 
2 0 
2 1 
2 2 
2 3 

3 4 
3 4 
3 4 
3 4 
3 4 
3 4 
3 4 
3 4 
3 4 
3 4 
3 4 
3 4 

所以数组生成正确,但我似乎无法将它们保存在某些数据结构中(队列 indices,这是输出中的第二组数字)。我也尝试过使用列表和引用,但我一直得到相同的结果。有人可以解释为什么会这样以及如何解决这个问题吗?谢谢。

在我看来,您似乎多次将同一个数组添加到队列中。当然,当您在最后打印时,您会看到同一数组中的最终值被多次打印出来。您需要复制数组(因为它是可变数据结构)。

查看问题的一种方法是观察您只创建了一次数组(在 multi_call 中),但您多次将它添加到队列中(在 do_multi_call 中) ).

更新

这是一个(相对)简单的例子,但也有同样的问题:

$ ocaml
        OCaml version 4.02.1

# let m n =
      let a = Array.make n 0 in
      let res = Array.make n [| |] in
      for i = 0 to n - 1 do
          for j = 0 to n - 1 do a.(j) <- i done;
          res.(i) <- a
      done;
      res;;
val m : int -> int array array = <fun>
# m 3;;
- : int array array = [|[|2; 2; 2|]; [|2; 2; 2|]; [|2; 2; 2|]|]

代码的(不正确的)想法是使用a设置矩阵的每一行,然后将其存储在矩阵中。但是只有一个a,所以矩阵的所有行实际上都是同一个数组。这是在 OCaml 中使用多维数组时相当常见的错误。您的原始代码类似,但使用的是队列而不是矩阵。