Ruby で循環参照してる配列で deep_dup するとどうなるか

deep_dup の話が Twitter で出たので試してみました。

ActiveSupport の #deep_dup をつかった場合

ActiveSupport#deep_dup の実装があるのでそれで試してみました。

require "active_support"
require "active_support/core_ext/object/deep_dup.rb"

a = [1, 2, 3]
a[3] = a

# error: in `map': stack level too deep (SystemStackError)
p a.deep_dup

と、いうことで SystemStackError で無事死亡。

Marshal.dump を使った場合

るりま の Object#clone のドキュメントに書いてある Marshal.dump をつかった例を試してみました。

a = [1, 2, 3]
a[3] = a

a2 = Marshal.load(Marshal.dump(a))
p a2
# => [1, 2, 3, [...]]
p a2[3]
# => [1, 2, 3, [...]]
p a2[3][3]
# => [1, 2, 3, [...]]

a2[2] = "homu"

p a2
# => [1, 2, "homu", [...]]
p a2[3]
# => [1, 2, "homu", [...]]
p a2[3][3]
# => [1, 2, "homu", [...]]

雰囲気うごいてそう。