我正在研究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;;
答案 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个点中。
如果您有其他想要解释的示例代码,可以在上面添加它们。如果它们很复杂,发布一个新问题可能会更好。