奇怪的行为存储功能导致OCaml

时间:2015-05-29 22:43:51

标签: 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 |]的所有数组,并将其存储在indices b.ml中。但是,我得到的输出是

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,这是输出中的第二组数字)。我也尝试使用list和refs,但我一直得到相同的结果。有人可以解释为什么会发生这种情况以及如何解决这个问题?感谢。

1 个答案:

答案 0 :(得分:1)

在我看来,你在队列中多次添加相同的数组。当然,当您在最后打印时,您会看到同一阵列中的最终值打印多次。你需要制作数组的副本(因为它是一个可变的数据结构)。

查看问题的一种方法是观察您只创建一个数组(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中使用多维数组这是一个相当常见的错误。您的原始代码类似,但是使用队列而不是矩阵。