deep copy

OCaml

# let orig = Array.init 8 (fun _ -> Array.create 8 "x");;
val orig : string array array =
  [|[|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|]|]

こんな配列を作っていて、これの複製を作りたい、かつその複製に対して変更を加える場合、Array.copyがそれらしく見えるものの、shallow copyなので複製に対する変更が元のarrayに影響する。

# let clone = Array.copy orig;;
val clone : string array array =
  [|[|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|]|]
# clone.(0).(0) <- "o";;
- : unit = ()
# orig;;
- : string array array =
[|[|"o"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|]|]
#

普段、RubyではMarshal.load(Marshal.dump xxx)としているので、同じことがOCamlではできまいか?と思って

# let orig = Array.init 8 (fun _ -> Array.create 8 "x");;
val orig : string array array =
  [|[|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|]|]
# let clone = (Marshal.from_string (Marshal.to_string orig []) 0 : string array array);;
val clone : string array array =
  [|[|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
    [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|]|]
# clone.(0).(0) <- "o";;
- : unit = ()
# orig;;
- : string array array =
[|[|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|];
  [|"x"; "x"; "x"; "x"; "x"; "x"; "x"; "x"|]|]
#

でけた