我有一个记录类型tt的数组 - 最初有更多组件;-) - 并且喜欢在for循环中更改其值:
type tt={mutable x: int};;
let f0={x= -1};;
let max=10;;
let ff=Array.create max f0;;
for i=0 to max-1 do ff.(i).x <- i;done;;
尽管如此,ff的所有字段都具有值9而不是0到9之间的值。是(。).x是否正确?我也试过
for i=0 to max-1 do f0.x <- i;ff.(i) <- f0;done;;
但结果相同......(我使用OCaml版本4.00.1) 怎么了?如果有人能给我一个提示,我会很高兴的!
答案 0 :(得分:8)
这是初学者对Array.create
和可变状态所做的经典错误。我已经详细解释了there。摘要是Array.create n foo
不会创建foo
的副本(怎么可能?),它会创建一个所有指向同一foo
的案例数组。
答案 1 :(得分:4)
问题是ff
数组的所有单元格都包含相同的元素,即f0
。您需要为每个单元格创建一个tt
类型的新元素。
这是一种方法:
type tt={mutable x: int};;
let max=10;;
let ff=Array.init max (fun i -> {x= i});;
现在您可以修改单元格而不影响其他单元格。
答案 2 :(得分:3)
问题在于,由于记录是可变的,因此它通过引用存储 而不是按值存储,就像您对非可变数据类型所期望的那样(作为整数)所以当你这样做时
let ff=Array.create 10 f0;;
您实际上存储了10个对同一记录的引用。然后每次迭代
for i=0 to max-1 do ff.(i).x <- i;done;;
只是多次更新相同的引用,所以由于上一次迭代是i = 9
,因此数组中包含的唯一真实记录会获得该值。
您需要做的是创建10个不同的记录,例如:
# type tt = {mutable x: int};;
type tt = { mutable x : int; }
# let f = Array.init 10 (fun i -> { x = -1});;
val f : tt array =
[|{x = -1}; {x = -1}; {x = -1}; {x = -1}; {x = -1}; {x = -1}; {x = -1};
{x = -1}; {x = -1}; {x = -1}|]
# f.(2).x <- 2;;
- : unit = ()
# f;;
- : tt array =
[|{x = -1}; {x = -1}; {x = 2}; {x = -1}; {x = -1}; {x = -1}; {x = -1};
{x = -1}; {x = -1}; {x = -1}|]