let a = Array.create 3 (Array.create 3 0)
let b = Array.init 3 (fun _ -> Array.init 3 (fun _ -> 0))
这两个数组都有签名int [] []和初始值[| [| 0; 0; 0 |]; [| 0; 0; 0 |]; [| 0; 0; 0 |] |。]
然而:
a.[0].[0] <- 3
b.[0].[0] <- 3
产生不同的结果:
a: [|[|3; 0; 0|]; [|3; 0; 0|]; [|3; 0; 0|]|]
b: [|[|3; 0; 0|]; [|0; 0; 0|]; [|0; 0; 0|]|]
b的结果是我对两者的期望。
对我来说,相同的签名应该以相同的方式行事似乎是合乎逻辑的。谁能告诉我我错过了什么?
答案 0 :(得分:3)
在第一个版本中,(Array.create 3 0)在作为参数传递之前被计算,因此数组的所有单元格都获得相同的值。 数组是引用类型,因此实际上所有单元都是相同的。
答案 1 :(得分:3)
Array.create的第二个参数是一个奇异值,用于初始化数组中的每个插槽。即,请考虑以下事项:
let a =
let v = Array.create 3 0
Array.create 3 v
v
存储在a
的所有3个广告位中,因此修改a
中的任何元素都会影响所有3个广告位。
编辑:还要考虑逻辑上的等同性:
let b =
let v = Array.create 3 0
Array.init 3 (fun _ -> v)
答案 2 :(得分:3)
对我来说,相同的签名应该以相同的方式行事似乎是合乎逻辑的。谁能告诉我我错过了什么?
<强>共享强>
使用Array.create
会生成共享相同值的元素数组。使用Array.init
调用函数来创建每个元素的值。
因此,这会分配两个数组:
let a = Array.create 3 (Array.create 3 0)
而这会分配四个数组:
let b = Array.init 3 (fun _ -> Array.init 3 (fun _ -> 0))
你可能更愿意用数组文字来思考它,前者相当于:
let xs = [|0;0;0|]
[|xs;xs;xs|]
而后者相当于:
let xs = [|0;0;0|]
let ys = [|0;0;0|]
let zs = [|0;0;0|]
[|xs;ys;zs|]