in reply to Re^2: hash ref mind blow
in thread hash ref mind blow
You might think of
$hash{a}{drinks}=1; $hash{b}{drinks}=2;
as a single hash, but that's not the case. There are three:
+-------+ +----------+ +-----------+ +-------------+ | %hash | +-->| Anon Ref | +->| Anon hash | +->| Anon scalar | +-------+ | +----------+ | +-----------+ | +-------------+ | a ----+ | addr ----+ | drinks ----+ | 1 | | b -----+ +----------+ +-----------+ +-------------+ +-------+ | | +----------+ +-----------+ +-------------+ +->| Anon Ref | +->| Anon hash | +->| Anon scalar | +----------+ | +-----------+ | +-------------+ | addr ----+ | drinks ----+ | 2 | +----------+ +-----------+ +-------------+
When you do %copy = %hash (which you wrote as %copy = %{ \%hash }), you are copying the keys and values of %hash. So what are the keys and values of %hash?
>perl -e"$h{a}{d}=1; $h{b}{d}=2; print qq{$_: $h{$_}\n} for keys %h;" a: HASH(0x22534c) b: HASH(0x2253a0)
That's all that's copied, nothing more. It will not make a copy of the referenced value and make a new reference to it. It simply copies the references. You end up with
+-------+ +----------+ +-----------+ +-------------+ | %hash | +-->| Anon Ref | +----->| Anon hash | +->| Anon scalar | +-------+ | +----------+ | +-----------+ | +-------------+ | a ----+ | addr -----+ | drinks ----+ | 1 | | b -----+ +----------+ | +-----------+ +-------------+ +-------+ | | | +----------+ | +-----------+ +-------------+ +->| Anon Ref | | +-->| Anon hash | +->| Anon scalar | +----------+ | | +-----------+ | +-------------+ | addr --------+ | drinks ----+ | 2 | +----------+ | | +-----------+ +-------------+ | | +-------+ +NEW-------+ | | | %copy | +-->| Anon Ref | | | +-------+ | +----------+ | | | a ----+ | addr -----+ | | b -----+ +----------+ | +-------+ | | | +NEW-------+ | +->| Anon Ref | | +----------+ | | addr --------+ +----------+
What you want is to do is to copy referenced values as well, and to do recursively, so that you end up with the following:
+-------+ +----------+ +-----------+ +-------------+ | %hash | +-->| Anon Ref | +->| Anon hash | +->| Anon scalar | +-------+ | +----------+ | +-----------+ | +-------------+ | a ----+ | addr ----+ | drinks ----+ | 1 | | b -----+ +----------+ +-----------+ +-------------+ +-------+ | | +----------+ +-----------+ +-------------+ +->| Anon Ref | +->| Anon hash | +->| Anon scalar | +----------+ | +-----------+ | +-------------+ | addr ----+ | drinks ----+ | 2 | +----------+ +-----------+ +-------------+ +-------+ +NEW-------+ +NEW--------+ +NEW----------+ | %copy | +-->| Anon Ref | +->| Anon hash | +->| Anon scalar | +-------+ | +----------+ | +-----------+ | +-------------+ | a ----+ | addr ----+ | drinks ----+ | 1 | | b -----+ +----------+ +-----------+ +-------------+ +-------+ | | +NEW ------+ +NEW--------+ +NEW----------+ +->| Anon Ref | +->| Anon hash | +->| Anon scalar | +----------+ | +-----------+ | +-------------+ | addr ----+ | drinks ----+ | 2 | +----------+ +-----------+ +-------------+
That's called a "deep copy" because it copies every level of the data structure. In contrast, a simple assignment is called a "shallow copy" because it only copies the immediate value (scalar/hash/array/...).
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Shallow vs deep copy (Was Re^3: hash ref mind blow)
by Anonymous Monk on Sep 25, 2008 at 15:38 UTC | |
by ikegami (Patriarch) on Sep 25, 2008 at 21:40 UTC |