Вопрос

I'm working with hashes in perl, but don't understand why the hash value changes in the following:

use strict;

sub test
{
    my ($value_ref) = @_;
    my %value = %$value_ref;
    $value{'abc'}{'xyz'} = 1;
}

my %hash;
$hash{'abc'}{'xyz'} = 0;
test (\%hash);
print "$hash{'abc'}{'xyz'}\n";

The above returns 1, why doesn't it return 0 like this it does here?

use strict;

sub test
{
    my ($value_ref) = @_;
    my %value = %$value_ref;
    $value{'abc'} = 1;
}

my %hash;
$hash{'abc'} = 0;
test (\%hash);
print "$hash{'abc'}\n";

I imagine it has to do with how I'm passing in %hash. What am I missing?

Это было полезно?

Решение

You are getting incorrect results because when you make your copy of the hash using my %value = %$value_ref; you are only getting the top-level keys. The second level, with the key 'xyz', is the one where value is actually stored so any changes to that reference are carried over. You are performing a shallow copy when you need a deep copy.

Luckily there is a CPAN module for that!

use strict;
use Storable qw(dclone);

sub test
{
    my ($value_ref) = @_;
    my %value = %{ dclone($value_ref) };
    $value{'abc'}{'xyz'} = 1;
}

my %hash;
$hash{'abc'}{'xyz'} = 0;
test (\%hash);
print "$hash{'abc'}{'xyz'}\n"; # prints 0

Другие советы

This is because the "second level" of your hash (IOW: the value for key 'abc') is itself a hash reference. While you're copying the contents of the hash referenced by $value_ref in your assignment:

my %value = %$value_ref;

...this is only doing a "shallow" copy.

When you modify the value for key 'xyz', you're modifying the same hash that is in the original structure passed to the sub.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top