ArrayのArrayをコピーする時、「こいつぁ…Shallow copyの匂いがするぜぇ…?」と疑うこと

普通に配列をDeep copyしたいならArray.copyで良いわけです。以下のコードを見る限りちゃんと、xとyが違う配列の実体を持っていそうだぞとわかる。

> let x = [|1..5|];;
val x : int [] = [|1; 2; 3; 4; 5|]
> let y = Array.copy x;;
val y : int [] = [|1; 2; 3; 4; 5|]
> y.[1] <- 300;;
val it : unit = ()
> y;;
val it : int [] = [|1; 300; 3; 4; 5|]
> x;;
val it : int [] = [|1; 2; 3; 4; 5|]

ただし、ArrayのArray(配列の配列)の場合、内側のArrayに題してcopyが適用されないので、要素毎のコピーであるDeep copyとはならない。

> let x = [|[|1..3|];[|1..3|]|];;
val x : int [] [] = [|[|1; 2; 3|]; [|1; 2; 3|]|]
> let y = Array.copy x;;
val y : int [] [] = [|[|1; 2; 3|]; [|1; 2; 3|]|]
> y.[1].[1] <- 300;;
val it : unit = ()
> y;;
val it : int [] [] = [|[|1; 2; 3|]; [|1; 300; 3|]|]
> x;;
val it : int [] [] = [|[|1; 2; 3|]; [|1; 300; 3|]|]

こうじゃなく、配列の要素全てをちゃんとコピーするにはArray.map+copyで内側のArrayを全コピーするようにする。

> let x = [|[|1..3|];[|1..3|]|];;
val x : int [] [] = [|[|1; 2; 3|]; [|1; 2; 3|]|]
> let y = Array.map (fun z -> Array.copy z) x;;
val y : int [] [] = [|[|1; 2; 3|]; [|1; 2; 3|]|]
> y.[1].[1] <- 300
;;
val it : unit = ()
> y;;
val it : int [] [] = [|[|1; 2; 3|]; [|1; 300; 3|]|]
> x;;
val it : int [] [] = [|[|1; 2; 3|]; [|1; 2; 3|]|]

そもそもフルフルにコピーしなきゃいけないようなコード書いてる時点でアレ感あるけど、まぁ嵌ったのでメモっておく。