在 OCaml 中对类型 int 数组数组进行乘法 table

Making a multiplication table of type int array array in OCaml

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

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

例如 table 2 的输出预计为 return

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

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

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

提供的答案有效。我不知道为什么——因为我们似乎在做同样的事情。我们用足够的 space 初始化一个数组,并用零填充它。然后我们使用嵌套的 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;;

您的问题是 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 个空数组 [||] 副本的外部数组,然后通过调用 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 并没有真正改变任何东西,只是 ref 5 本身是可变的。假设我们不打算修改引用,而只是更改内部数组的内容。然后你会看到这样的东西:

# 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}|]|]

如您所见,所有内部数组似乎都发生了变化。那是因为只有一个内部数组。所以实际上只有一个数组发生了变化。外部数组的所有 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) := 99;;
- : unit = ()
# a;;
- : int ref array array =
[|[|{contents = 99}; {contents = 99}; {contents = 99}|];
  [|{contents = 99}; {contents = 99}; {contents = 99}|];
  [|{contents = 99}; {contents = 99}; {contents = 99}|]|]

不出所料,所有元素都变成了 99,因为只有一个引用出现在所有 9 个位置。

如果您想解释其他示例代码,可以在上面添加它们。如果它们很复杂,最好 post 一个新问题。