f#:初始化数组数组

时间:2011-05-31 17:02:22

标签: f#

在以下代码中,是否为数组A = B的数组?

let A =  Array.init  3 (fun _ -> Array.init 2 (fun _ -> 0))
let defaultCreate n defaultValue = Array.init n (fun _ -> defaultValue)
let B = defaultCreate 3 (defaultCreate 2 0)

如果我将值分配给A and B,它们会有所不同,发生了什么?感谢。

 for i = 0 to 2 do
     for j = 0 to 1 do
            A.[i].[j] <-i + j
            B.[i].[j] <-i + j
 printfn "%A vs %A" A  B

A = [|[|0; 1|]; [|1; 2|]; [|2; 3|]|] and B = [|[|2; 3|]; [|2; 3|]; [|2; 3|]|]

2 个答案:

答案 0 :(得分:3)

let B = defaultCreate 3 (defaultCreate 2 0)

您创建一个数组,然后将此数组用作每个单元格的值。 就像你做了这样的事情:

let a = [|1; 2; 3; 4|]
let b = [|a; a; a; a|]

同一个数组a用于每个单元格(想想指向a的指针,你已经习惯了C)。因此,修改b.[0].[1]将改变每a.[1]

在我的样本中:

> b.[0].[1] <- 10;;
val it : unit = ()

> b;;
[|[|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]; [|1; 10; 3; 4|]|]

您的代码也会发生同样的事情。

答案 1 :(得分:0)

它们不一样。

数组是引用类型,存储在堆上。当您使用另一个数组作为默认值创建数组时,您将一遍又一遍地存储对同一数组的引用。

数字是另一回事。它们是不可变的,并且按值存储在堆栈中。因此,您无法将1的值更改为1以外的任何内容。

要创建“锯齿状”数组,您需要从初始化程序内部调用Array.init到第一个Array.init调用,为每个插槽创建新数组。

也;如果您希望在每个插槽中具有相同的值,则可以使用Array.create。但要注意参考类型。

let A = Array.init 3 (fun _ -> Array.create 2 0)