在OCaml中创建int数组类型的乘法表

时间:2016-07-10 03:11:17

标签: arrays ocaml

我正在研究OCaml命令式编程的一些基础知识。

我正在尝试创建一个简单的int数组数组,其中包含乘法表,直到我作为参数传递的整数。

例如,table 2的输出预计将返回

  

[| [| 1; 2 |]; [| 2; 4 |] |]

我的代码不起作用。我首先用足够的空间初始化一个数组并用零填充它。 x的迭代适用于数组的索引,因为数组的每个条目都被填充但(x+1) * (y+1)部分有问题。

table 2的结果是[|[|2;4|];[|2;4|]|],好像它没有通过x正确迭代。

提供的答案有效。我不知道为什么 - 因为我们似乎正在做同样的事情。我们用足够的空间初始化一个数组并用零填充它。然后我们使用嵌套的for循环来填充它。这是因为答案使用了第一个for循环吗?为什么呢?

我的代码:

let table n =
    let a = Array.make n (Array.make n 0) in
    for x = 0 to n-1 do   
        for y = 0 to n-1 do   
            a.(x).(y) <- ((x+1) * (y+1));
        done;
    done;
    a;;

答案:

let table n =
    let a = Array.make n [||] in
    for x = 0 to n-1 do
        a.(x) <- Array.make n 0
    done;
    for y = 0 to n-1 do
        for x = 0 to n-1 do
            a.(x).(y) <- (x+1)*(y+1)
        done
    done;
    a;;

1 个答案:

答案 0 :(得分:3)

您的问题是Array.make将使用相同的单个值填充数组。因此,您的外部数组不包含n个不同的数组,但是n引用了相同的数组。

使用以下代码会得到相同的不良结果:

let aa = Array.make n 0 in
let a = Array.make n [||] in
for x = 0 to n - 1 do
    a.(x) <- aa
done

编写工作示例是为了避免此问题。首先,它创建一个包含空数组n的{​​{1}}个副本的外部数组,然后通过调用{{1}将其填充到[||] 个不同的数组对象中每一个。

要调整代码,可以改用n,它为每个不同的数组元素调用指定的函数:

Array.make

或者您可以使用Array.init

let a = Array.init n (fun _ -> Array.make n 0)

<强>更新

在示例中使用Array.make_matrix代替let a = Array.make_matrix n n 0 并没有真正改变任何内容,只有ref 5本身是可变的。假设我们不打算修改引用,只是更改内部数组的内容。然后你会看到这样的事情:

0

如您所见,所有内部数组似乎都在发生变化。那是因为只有一个内部阵列。所以真的只有一个阵列发生了变化。外部数组在其所有3个元素中包含这一个数组。

接下来,请注意只有一次拨打ref 5。这意味着所有引用(所有9个引用)都是相同的引用。您可以在以下内容中看到:

# let a = Array.make 3 (Array.make 3 (ref 5));;
val a : int ref array array =
  [|[|{contents = 5}; {contents = 5}; {contents = 5}|];
    [|{contents = 5}; {contents = 5}; {contents = 5}|];
    [|{contents = 5}; {contents = 5}; {contents = 5}|]|]
# a.(1).(2) <- ref 88;;
- : unit = ()
# a;;
- : int ref array array =
[|[|{contents = 5}; {contents = 5}; {contents = 88}|];
  [|{contents = 5}; {contents = 5}; {contents = 88}|];
  [|{contents = 5}; {contents = 5}; {contents = 88}|]|]

正如预期的那样,所有元素都变为99,因为只有一个参考显示在所有9个点中。

如果您有其他想要解释的示例代码,可以在上面添加它们。如果它们很复杂,发布一个新问题可能会更好。