Ocaml - Accessing components in an array of records

ⅰ亾dé卋堺 提交于 2019-12-10 15:07:31

问题


I have a array of record type tt - originally with more components ;-) - and like to change its values within a for loop:

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;;

Nevertheless, all fields of ff have the value 9 instead of having values from 0 to 9. Is ff.(i).x correct? I also tried

for i=0 to max-1 do f0.x <- i;ff.(i) <- f0;done;;

but with the same result... (I'm using OCaml version 4.00.1) What is wrong? I would be happy if somebody could give me a hint!


回答1:


This is a classic mistake that beginners do with Array.create and mutable state. I have explained it in detail there. The summary is that Array.create n foo does not create copies of foo (how could it?), it creates an array of cases all pointing to the same foo.




回答2:


The problem is that all cells of the ff array contain the same element, namely f0. You need to create a fresh element of type tt for each cell. This is a way to do so:

type tt={mutable x: int};;
let max=10;;
let ff=Array.init max (fun i -> {x= i});;

Now you can modify a cell without affecting the other cells.




回答3:


The problem is that, since the record is mutable, it is stored by reference and not by value as you would expect from a non mutable data type (as an integer) so when you do

let ff=Array.create 10 f0;;

you are actually storing 10 references to the same record. And then each iteration of

for i=0 to max-1 do ff.(i).x <- i;done;;

just updates the same reference multiple times, so since last iteration is with i = 9 then the only real record contained in the array gets that value.

What you need to do is to create 10 different record such with:

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


来源:https://stackoverflow.com/questions/14001569/ocaml-accessing-components-in-an-array-of-records

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!